1. 程式人生 > >C#實現簡易ajax呼叫後臺方法

C#實現簡易ajax呼叫後臺方法

在當前WEB當中,有些人都會拋棄asp.net的伺服器控制元件,轉而使用ajax來進行資料的互動和儲存.

  當我們大量使用ajax的時候,對於新手而言,肯定會建立很多的ashx或aspx頁面,通過拼接引數,在ashx或aspx中對引數進行解析,

  並根據某些特定的引數進行解析來判斷當前的請求屬於哪種型別的操作,然後手動獲取Request.QueryString、Params、Form內的值,來實現功能.大致程式碼如下:


複製程式碼

 1 //html
 2 名字:<input id="name" type="text"/>
 3 <input type="button" value="查詢" onclick="search()"/>
 4 <script type="text/javascript">
 5     function search(){
 6         var name = $('#name').val();
 7         //省略驗證過程
 8         $.ajax({
 9             url: 'Customer.ashx',
10             data: { type: 'search', name : name },
11             dataType: 'json',
12             success: function(json){
13                 //對於獲取的資料執行相關的操作,如:繫結、顯示等
14             }
15         });
16     };
17 </script>
18 //ashx
19 public void ProcessRequest(HttpContext context)
20 {
21     var type = context.Request.Params["type"];
22     if(type == "search")
23     {
24         var name = context.Request.Params["name"];
25         //獲取資料,並轉化為json
26         var json = ...//省略
27         context.Response.Write(json);
28     }
29 }
複製程式碼

在大量的重複這些編寫這些程式碼的情況下,眾多的新手們肯定都會跟我一樣,蛋疼啊,而且隨著業務及模組的不斷增加,這些個ashx或aspx,那個量還不是一般的多呢.

  而且每個都只是做一些判斷,根本沒什麼重要的業務在裡面,於是乎我們就在想,有沒有什麼方法可以讓我們在ajax內傳遞某些引數,達到直接反射類,訪問對應的方法,自動處理引數等.

  根據以上的一些要求,的確可以讓我們在編碼過程當中,減少很多的困惑和麻煩.那我們現在就一步步開始吧.

  首先,我們先從ajax開始,傳遞某些特定的值來反射對應的類,那麼我們的第一反應就是將類的整個完整命名傳遞過去(因為我們並不能保證所有要呼叫的類都在同一個程式集內).

  那麼我們就在js內定義2個引數分別為assembly和fullName吧.我們假設Customer業務類的FullName為SysBLL.CustomerBLL且所在的程式集為SysBLL.

  那麼前面的例子ajax的修改大致如下:


複製程式碼

 1 <script type="text/javascript">
 2     function search(){
 3         var name = $('#name').val();
 4         //省略驗證過程
 5         $.ajax({
 6             url: 'BLLAshx.ashx',
 7             data: { assemlby : 'SysBLL', fullName: 'SysBLL.CustomerBLL', method: 'Search', name : name },
 8             dataType: 'json',
 9             success: function(json){
10                 //對於獲取的資料執行相關的操作,如:繫結、顯示等
11             }
12         });
13     };
14 </script>
複製程式碼 從我們的需求上,我們瞭解到,我們只需要一個ashx來作為代理,去反射對應的類和方法,並從傳遞的引數中過濾出方法所需要的引數,最後呼叫方法取得返回值.程式碼大致如下:
 1 View Code 
 2  //ashx
 3  namespace Common
 4  {
 5      public class BLLAshx : IHttpHandler
 6      {
 7          public void ProcessRequest(HttpContext context)
 8          {
 9              string assemblyName = context.Request.QueryString["assemlby"], fullName = context.Request.Params["fullName"];
10              var bllType = Assembly.Load(assemblyName).GetType(fullName);
11                      
12              var methodName = context.Request.Params["method"];
13              var method = bllType.GetMethod(methodName);
14              if (null != method)
15              {
16                  string[] parameterValues = GetMethodParameterValues(context.Request, method);
17  
18                  var instance = Activator.CreateInstance(bllType);
19  
20                  var result = method.ReturnType == typeof(void) ? "{}" : method.Invoke(instance, parameterValues).ToString();
21  
22                  //以上Invoke省略了判斷以及捕捉異常
23                  context.Response.Write(result);
24              }
25              else
26              {
27                  //返回不存在方法的提示
28              }
29          }
30  
31          private string[] GetMethodParameterValues(HttpRequest request, MethodInfo method)
32          {
33              string[] parameterValues = null;
34              var methodParameters = method.GetParameters();
35              if (0 < methodParameters.Length)
36              {
37                  parameterValues = new string[methodParameters.Length];
38                  for (int i = 0; i < methodParameters.Length; i++)
39                  {
40                      parameterValues[i] = request.Params[methodParameters[i].Name];
41                  }
42              }
43              return parameterValues;
44          }
45      }
46  }
47  //CustomerBLL
48  namespace SysBLL
49  {
50      public class CustomerBLL
51      {
52          public string Search(string name)
53          {
54              var json = ...//獲取資料
55              return json;
56          }
57      }
58  }
複製程式碼  

對於以上的ashx,我們需要在web專案中,新建一個名為BLLAshx的ashx檔案,但是我們不要.cs的檔案,並作如下修改:

<%@ WebHandler Language="C#" CodeBehind="BLLAshx.cs" Class="Common.BLLAshx" %>

  現在我們再次回到ajax呼叫的地方,大家都會發現我們的引數列表室在太長了,因此大家可能會想用一些方法來改善,比如:連ashx都懶的重複去寫了,想直接在url中把彌名稱空間、類、方法直接放進去來替代,想到這一步的時候,我們就需要配置web.config了,假設我們想要的規則是SysBLL/SysBLL.CustomerBLL.Search,配置如下:

<httpHandlers>
    <add path="*/*.*.*.do" type="Common.BLLAshx" verb="GET,POST"/>
</httpHandlers>

  有人會問為什麼這邊要.do,而不直接省略呢?因為如果不加.do,那麼就會將其他的請求也都轉向我們的ashx,例如:js、css檔案等,大家可以自己測試看看.因為我們使用了地址對映,因此我們的js以及ashx程式碼又要做一些改動了.大致修改如下:

 

//ashx
namespace Common
{
public class BLLAshx : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string assemblyName = context.Request.QueryString["assemlby"], fullName = context.Request.Params["fullName"];
var bllType = Assembly.Load(assemblyName).GetType(fullName);

var methodName = context.Request.Params["method"];
var method = bllType.GetMethod(methodName);
if (null != method)
{
string[] parameterValues = GetMethodParameterValues(context.Request, method);

var instance = Activator.CreateInstance(bllType);

var result = method.ReturnType == typeof(void) ? "{}" : method.Invoke(instance, parameterValues).ToString();

//以上Invoke省略了判斷以及捕捉異常
context.Response.Write(result);
}
else
{
//返回不存在方法的提示
}
}

private string[] GetMethodParameterValues(HttpRequest request, MethodInfo method)
{
string[] parameterValues = null;
var methodParameters = method.GetParameters();
if (0 < methodParameters.Length)
{
parameterValues = new string[methodParameters.Length];
for (int i = 0; i < methodParameters.Length; i++)
{
parameterValues[i] = request.Params[methodParameters[i].Name];
}
}
return parameterValues;
}
}
}
//CustomerBLL
namespace SysBLL
{
public class CustomerBLL
{
public string Search(string name)
{
var json = ...//獲取資料
return json;
}
}
}

 

ashx的調整,我們只要修改ProcessRequest方法,程式碼大致如下:

 

var reg = new Regex(@"(?<assembly>\w+)\/(?<class>\w+\.\w+)\.(?<method>\w+)\.");
var groups = reg.Match(context.Request.AppRelativeCurrentExecutionFilePath).Groups;
if (4 == groups.Count)
{
string assemblyName = groups["assembly"].Value, fullName = groups["class"].Value;
var bllType = Assembly.Load(assemblyName).GetType(fullName);

var methodName = groups["method"].Value;
var method = bllType.GetMethod(methodName);
if (null != method)
{
string[] parameterValues = GetMethodParameterValues(context.Request, method);

var instance = Activator.CreateInstance(bllType);

var result = method.ReturnType == typeof(void) ? "{}" : method.Invoke(instance, parameterValues).ToString();
//以上Invoke省略了判斷以及捕捉異常
context.Response.Write(result);
}
else
{
//返回不存在方法的提示
}
}
else
{
//url匹配不正確
}

 

有人可能會問為什麼要重複SysBLL/SysBLL呢?其實可以省略其中的一個,但是條件是程式集必須要跟這個字首一樣才能省略.

  如果大家想要省略其中一次SysBLL,那麼正則的匹配規則也要相應的調整一下,只要將(?<class>\w+.\w+)中的.\w+去掉即可.

  大致的實現流程就到這裡了,我們已經將大部分的需求基本完成了,還有一些遺留的問題留給大家去完善啦,比如:呼叫的方法引數必須都是string型別,方法的返回值也必須要是string型別,反射的類不能是泛型型別的等等.

 

轉自 https://www.cnblogs.com/ahl5esoft/archive/2012/06/27/2565496.html