点击这里给我发消息 点击这里给我发消息

ASP.NET WebForm也可以这样用Ajax(二)

添加时间:2013-12-6
    相关阅读: 设计 ASP ASP.NET 页面 程序 JavaScript 框架

6. 主要基类:AjaxBasePage类

如下代码:

  1. public class AjaxBasePage : System.Web.UI.Page  
  2. {  
  3.     /// <summary>  
  4.     /// 是否是一个ajax请求。  
  5.     /// </summary>  
  6.     public bool IsAjaxRequest { get; private set; }  
  7.  
  8.     /// <summary>  
  9.     ///  如果是Ajax请求,劫持页面生命周期的PreInit的事件,直接返回Response  
  10.     /// </summary>  
  11.     protected override void OnPreInit(EventArgs e)  
  12.     {  
  13.         AjaxRequest ajaxRequest = AjaxRequest.GetInstance(Request.Form);  
  14.         this.IsAjaxRequest = ajaxRequest.IsAjaxRequest;  
  15.  
  16.         if (this.IsAjaxRequest)  
  17.         {  
  18.             AjaxApplication ajaxApplication = new AjaxApplication(this, ajaxRequest);  
  19.             ajaxApplication.EndRequest();  
  20.         }  
  21.         else 
  22.         {  
  23.             // 如果不是Ajax请求,继续执行页面生命周期的剩余事件  
  24.             base.OnPreInit(e);  
  25.         }  
  26.     }  

该类重写了PreInit方法,判断请求是否是一个Ajax请求。通过AjaxRequest类接收并处理接收到的请求,提取出一些有效的数据,比如说是否是一个Ajax请求,方法的名字,参数列表(AjaxParameter类)。

至于AjaxParameter类,内部用的数据结构其实是一个字典,并使用索引来提供对数据的方便访问,提供一个Count属性,方便获取参数的个数。     如下代码

  1. public class AjaxParameter  
  2.     {  
  3.         private IDictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();  
  4.    
  5.         /// <summary>  
  6.         /// 返回参数的个数。  
  7.         /// </summary>  
  8.         public int Count  
  9.         {  
  10.             get  
  11.             {  
  12.                 return this.m_DictionaryParamsData.Count;  
  13.             }  
  14.         }  
  15.    
  16.         /// <summary>  
  17.         /// 索引具体参数的值。  
  18.         /// </summary>  
  19.         /// <param name="index"></param>  
  20.         /// <returns></returns>  
  21.         public string this[int index]  
  22.         {  
  23.             get  
  24.             {  
  25.                 if (index >= 5 || index < 0)  
  26.                 {  
  27.                     throw new NotSupportedException("请求方法的参数的个数限制为:0-5");  
  28.                 }  
  29.                 return this.m_DictionaryParamsData[index];  
  30.             }  
  31.         }  
  32.    
  33.         public AjaxParameter(IDictionary<int, string> paramsData)  
  34.         {  
  35.             this.m_DictionaryParamsData = paramsData;  
  36.         }  
  37.     } 

AjaxRequest类的设计思路其实是模仿HttpContext设计,HttpContext能够从基础的http请求报文分析出以后处理将要用到的数据(response,request,session,cookie等等)数据,而AjaxRequest通过分析Ajax的Post请求的数据域 Data分析出各种以后会用到的数据。如下是该类的代码:

  1. public class AjaxRequest  
  2.     {  
  3.         private Dictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();  
  4.         private AjaxParameter m_AjaxParameter;  
  5.         private int m_Count = 0;  
  6.    
  7.         #region 属性  
  8.         /// <summary>  
  9.         /// 是否是一个Ajax请求。  
  10.         /// </summary>  
  11.         public bool IsAjaxRequest { get; private set; }  
  12.    
  13.         /// <summary>  
  14.         /// 请求的方法名字。  
  15.         /// </summary>  
  16.         public string MethodName { get; private set; }  
  17.    
  18.         /// <summary>  
  19.         /// 参数数据。  
  20.         /// </summary>  
  21.         public AjaxParameter Parameters  
  22.         {  
  23.             get { return this.m_AjaxParameter; }  
  24.         }  
  25.         #endregion  
  26.    
  27.         #region 构造函数  
  28.         private AjaxRequest(NameValueCollection nameValueCollection)  
  29.         {  
  30.             this.IsAjaxRequest = nameValueCollection["isAjaxRequest"] == "true";  
  31.             if (this.IsAjaxRequest)  
  32.             {  
  33.                 this.MethodName = nameValueCollection["MethodName"];  
  34.    
  35.                 foreach (string value in nameValueCollection)  
  36.                 {  
  37.                     string formKey = string.Format("param{0}"this.m_Count);  
  38.                     if (nameValueCollection[formKey] != null)  
  39.                     {  
  40.                         this.m_DictionaryParamsData.Add(this.m_Count, nameValueCollection[formKey]);  
  41.                         this.m_Count++;  
  42.                     }  
  43.                 }  
  44.                 m_AjaxParameter = new AjaxParameter(this.m_DictionaryParamsData);  
  45.             }  
  46.         }  
  47.    
  48.         #endregion  
  49.    
  50.         #region 实例方法  
  51.         public static AjaxRequest GetInstance(NameValueCollection nameValueCollection)  
  52.         {  
  53.             return new AjaxRequest(nameValueCollection);  
  54.         }  
  55.         #endregion  
  56.    
  57.         #region ToString  
  58.         public override string ToString()  
  59.         {  
  60.             return this.MethodName;  
  61.         }  
  62.         #endregion  
  63.     } 

通过分析AjaxRequest的属性IsAjaxRequest可判断是否为Ajax请求,若该请求为一个Ajax请求,那么创建一个AjaxApplication实例,在创建AjaxApplication实例的过程中会利用当前页面和AjaxRequest提供的数据进行实际方法的调用(反射),该类是执行Ajax方法的核心类,其中会判断是否读取的到的方法是一个有效的方法,并判断从JS中AjaxApplication传入的参数类型的有效性,目前只提供对以下13中参数提供支持,如下:

  1. (String、Boolean、Int32、Int64、UInt32、UInt64、Single、Double、Decimal、DateTime、DateTimeOffset、TimeSpan、Guid) 

如果方法中出现非以上类型,将会抛出异常。为了方便Ajax的调试,在JS前段类库中我会对异常进行处理,并抛出Error,Error信息有效的截取了继承自Exception的抛出信息,至于如何获    得更加详细的JS调试信息,以后JS库中可能会做提供更加详细的调用信息,毕竟框架是在改进中进行的。如下是AjaxApplication类的具体代码:

  1. public class AjaxApplication  
  2.     {  
  3.         private AjaxBasePage m_AjaxBasePage;  
  4.         private object m_ResponseData;  
  5.    
  6.         public AjaxApplication(AjaxBasePage ajaxBasePage, AjaxRequest ajaxRequest)  
  7.         {  
  8.             this.m_AjaxBasePage = ajaxBasePage;  
  9.             Type ajaxBasePageType = ajaxBasePage.GetType();  
  10.             MethodInfo methodInfo = ajaxBasePageType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)  
  11.                                         .FirstOrDefault(item => item.Name == ajaxRequest.MethodName);  
  12.             object[] parameterData = this.GetParameterData(ajaxRequest, methodInfo);  
  13.    
  14.             if (methodInfo.IsStatic)  
  15.             {  
  16.                 this.m_ResponseData = methodInfo.Invoke(null, parameterData);  
  17.             }  
  18.             else 
  19.             {  
  20.                 this.m_ResponseData = methodInfo.Invoke(ajaxBasePage, parameterData);  
  21.             }  
  22.         }  
  23.    
  24.         /// <summary>  
  25.         /// 获取参数数据。  
  26.         /// </summary>  
  27.         private object[] GetParameterData(AjaxRequest ajaxRequest, MethodInfo methodInfo)  
  28.         {  
  29.             if (methodInfo != null)  
  30.             {  
  31.                 ParameterInfo[] parameterInfos = methodInfo.GetParameters();  
  32.    
  33.                 if (parameterInfos.Length > 5)  
  34.                 {  
  35.                     throw new NotSupportedException("最多支持5个参数");  
  36.                 }  
  37.    
  38.                 if (parameterInfos.Length > ajaxRequest.Parameters.Count)  
  39.                 {  
  40.                     throw new ArgumentException("缺少参数!");  
  41.                 }  
  42.    
  43.                 List<object> parameterData = new List<object>(parameterInfos.Length);  
  44.                 for (int i = 0; i < parameterInfos.Length; i++)  
  45.                 {  
  46.                     ParameterInfo parameterInfo = parameterInfos[i];  
  47.                     string paramValue = ajaxRequest.Parameters[i];  
  48.    
  49.                     try 
  50.                     {  
  51.                         parameterData.Add(ParseAjaxParameter(paramValue, parameterInfo));  
  52.                     }  
  53.                     catch (FormatException)  
  54.                     {  
  55.                         string format = string.Format("传入静态方法 {0} 的第 {1} 个(从0开始计数)参数类型不匹配,应该为 {2} 类型 请检查!", methodInfo.Name, i, parameterInfo.ParameterType.Name);  
  56.                         throw new FormatException(format);  
  57.                     }  
  58.                 }  
  59.                 return parameterData.ToArray();  
  60.             }  
  61.             else 
  62.             {  
  63.                 throw new InvalidOperationException("没有发现此方法,请检查该方法签名(方法必须为public)");  
  64.             }  
  65.         }  
  66.    
  67.         /// <summary>  
  68.         /// 类型转换。支持 String、Boolean、Int32、Int64、UInt32、UInt64、Single、Double、Decimal、DateTime、DateTimeOffset、TimeSpan、Guid  
  69.         /// </summary>  
  70.         private object ParseAjaxParameter(string ajaxParameterValue, ParameterInfo parameterInfo)  
  71.         {  
  72.             object obj;  
  73.             if (parameterInfo.ParameterType == typeof(String))  
  74.             {  
  75.                 obj = ajaxParameterValue;  
  76.             }  
  77.             else if (parameterInfo.ParameterType == typeof(Boolean))  
  78.             {  
  79.                 obj = bool.Parse(ajaxParameterValue);  
  80.             }  
  81.             else if (parameterInfo.ParameterType == typeof(Int32))  
  82.             {  
  83.                 obj = Int32.Parse(ajaxParameterValue);  
  84.             }  
  85.             else if (parameterInfo.ParameterType == typeof(UInt32))  
  86.             {  
  87.                 obj = UInt32.Parse(ajaxParameterValue);  
  88.             }  
  89.             else if (parameterInfo.ParameterType == typeof(UInt64))  
  90.             {  
  91.                 obj = UInt64.Parse(ajaxParameterValue);  
  92.             }  
  93.             else if (parameterInfo.ParameterType == typeof(Single))  
  94.             {  
  95.                 obj = Single.Parse(ajaxParameterValue);  
  96.             }  
  97.             else if (parameterInfo.ParameterType == typeof(Double))  
  98.             {  
  99.                 obj = Double.Parse(ajaxParameterValue);  
  100.             }  
  101.             else if (parameterInfo.ParameterType == typeof(Decimal))  
  102.             {  
  103.                 obj = Decimal.Parse(ajaxParameterValue);  
  104.             }  
  105.             else if (parameterInfo.ParameterType == typeof(DateTime))  
  106.             {  
  107.                 obj = DateTime.Parse(ajaxParameterValue);  
  108.             }  
  109.             else if (parameterInfo.ParameterType == typeof(DateTimeOffset))  
  110.             {  
  111.                 obj = DateTimeOffset.Parse(ajaxParameterValue);  
  112.             }  
  113.             else if (parameterInfo.ParameterType == typeof(TimeSpan))  
  114.             {  
  115.                 obj = TimeSpan.Parse(ajaxParameterValue);  
  116.             }  
  117.             else if (parameterInfo.ParameterType == typeof(Guid))  
  118.             {  
  119.                 obj = Guid.Parse(ajaxParameterValue);  
  120.             }  
  121.             else 
  122.             {  
  123.                 throw new NotSupportedException("方法参数类型不支持!");  
  124.             }  
  125.             return obj;  
  126.         }  
  127.    
  128.         /// <summary>  
  129.         /// 结束页面生命周期,同时直接执行应用程序生命周期的EndRequest事件。  
  130.         /// </summary>  
  131.         public void EndRequest()  
  132.         {  
  133.             HttpResponse response = this.m_AjaxBasePage.Page.Response;  
  134.             response.ContentType = "application/json";  
  135.             response.Clear();  
  136.             JavaScriptSerializer jsonSerializer2 = new JavaScriptSerializer();  
  137.             response.Write(jsonSerializer2.Serialize(new JsonResponse { IsSuccess = true, Message = "处理成功", ResponseData = this.m_ResponseData }));  
  138.             response.End();  
  139.         }  
  140.     } 

当初始化了一个AjaxApplication实例后, 可以调用该实例的EndRequest()方法,来结束Ajax请求。该方法内部最后调用Response.End()方法来结束页面生命周期和大部分管线事件。

并用JsonResponse类来封装返回数据。

  1. public class JsonResponse  
  2. {  
  3.     public bool IsSuccess { get; set; }  
  4.     public string Message { get; set; }  
  5.     public object ResponseData { get; set; }  

该类最后一个参数即承载了调用方法的返回值,为一个Object类型,也就是说,框架可以支持任何类型的返回值,当然该类型可以被序列化。

7. 回过头来再看Ajax请求,针对返回值可以这样用:

  1. PowerAjax.AsyncAjax('TestAjaxMethod', [1, 2, "333""sss"], function (SucceessResponse) {  
  2.     if (SucceessResponse.IsSuceess) {  
  3.         alert("恭喜,该ajax方法调用成功!");  
  4.         Process(SucceessResponse.ResponseData); // 处理返回的数据,这里可能需要你自己实现了,因为我无法判断你要返回的是什么东西,这是个Object  
  5.     } else {  
  6.         alert("这是操作错误奥,不是内部异常,内部异常的抛出会我内部会处理的!");  
  7.         alert("错误信息:" + SucceessResponse.Message);  
  8.     }  
  9. });  

以上是试水的东西,希望各位大牛指正。

原文链接:

咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册