6. 主要基类:AjaxBasePage类
如下代码:
- public class AjaxBasePage : System.Web.UI.Page
- {
- /// <summary>
- /// 是否是一个ajax请求。
- /// </summary>
- public bool IsAjaxRequest { get; private set; }
- /// <summary>
- /// 如果是Ajax请求,劫持页面生命周期的PreInit的事件,直接返回Response
- /// </summary>
- protected override void OnPreInit(EventArgs e)
- {
- AjaxRequest ajaxRequest = AjaxRequest.GetInstance(Request.Form);
- this.IsAjaxRequest = ajaxRequest.IsAjaxRequest;
- if (this.IsAjaxRequest)
- {
- AjaxApplication ajaxApplication = new AjaxApplication(this, ajaxRequest);
- ajaxApplication.EndRequest();
- }
- else
- {
- // 如果不是Ajax请求,继续执行页面生命周期的剩余事件
- base.OnPreInit(e);
- }
- }
- }
该类重写了PreInit方法,判断请求是否是一个Ajax请求。通过AjaxRequest类接收并处理接收到的请求,提取出一些有效的数据,比如说是否是一个Ajax请求,方法的名字,参数列表(AjaxParameter类)。
至于AjaxParameter类,内部用的数据结构其实是一个字典,并使用索引来提供对数据的方便访问,提供一个Count属性,方便获取参数的个数。 如下代码
- public class AjaxParameter
- {
- private IDictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();
- /// <summary>
- /// 返回参数的个数。
- /// </summary>
- public int Count
- {
- get
- {
- return this.m_DictionaryParamsData.Count;
- }
- }
- /// <summary>
- /// 索引具体参数的值。
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public string this[int index]
- {
- get
- {
- if (index >= 5 || index < 0)
- {
- throw new NotSupportedException("请求方法的参数的个数限制为:0-5");
- }
- return this.m_DictionaryParamsData[index];
- }
- }
- public AjaxParameter(IDictionary<int, string> paramsData)
- {
- this.m_DictionaryParamsData = paramsData;
- }
- }
AjaxRequest类的设计思路其实是模仿HttpContext设计,HttpContext能够从基础的http请求报文分析出以后处理将要用到的数据(response,request,session,cookie等等)数据,而AjaxRequest通过分析Ajax的Post请求的数据域 Data分析出各种以后会用到的数据。如下是该类的代码:
- public class AjaxRequest
- {
- private Dictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();
- private AjaxParameter m_AjaxParameter;
- private int m_Count = 0;
- #region 属性
- /// <summary>
- /// 是否是一个Ajax请求。
- /// </summary>
- public bool IsAjaxRequest { get; private set; }
- /// <summary>
- /// 请求的方法名字。
- /// </summary>
- public string MethodName { get; private set; }
- /// <summary>
- /// 参数数据。
- /// </summary>
- public AjaxParameter Parameters
- {
- get { return this.m_AjaxParameter; }
- }
- #endregion
- #region 构造函数
- private AjaxRequest(NameValueCollection nameValueCollection)
- {
- this.IsAjaxRequest = nameValueCollection["isAjaxRequest"] == "true";
- if (this.IsAjaxRequest)
- {
- this.MethodName = nameValueCollection["MethodName"];
- foreach (string value in nameValueCollection)
- {
- string formKey = string.Format("param{0}", this.m_Count);
- if (nameValueCollection[formKey] != null)
- {
- this.m_DictionaryParamsData.Add(this.m_Count, nameValueCollection[formKey]);
- this.m_Count++;
- }
- }
- m_AjaxParameter = new AjaxParameter(this.m_DictionaryParamsData);
- }
- }
- #endregion
- #region 实例方法
- public static AjaxRequest GetInstance(NameValueCollection nameValueCollection)
- {
- return new AjaxRequest(nameValueCollection);
- }
- #endregion
- #region ToString
- public override string ToString()
- {
- return this.MethodName;
- }
- #endregion
- }
通过分析AjaxRequest的属性IsAjaxRequest可判断是否为Ajax请求,若该请求为一个Ajax请求,那么创建一个AjaxApplication实例,在创建AjaxApplication实例的过程中会利用当前页面和AjaxRequest提供的数据进行实际方法的调用(反射),该类是执行Ajax方法的核心类,其中会判断是否读取的到的方法是一个有效的方法,并判断从JS中AjaxApplication传入的参数类型的有效性,目前只提供对以下13中参数提供支持,如下:
- (String、Boolean、Int32、Int64、UInt32、UInt64、Single、Double、Decimal、DateTime、DateTimeOffset、TimeSpan、Guid)
如果方法中出现非以上类型,将会抛出异常。为了方便Ajax的调试,在JS前段类库中我会对异常进行处理,并抛出Error,Error信息有效的截取了继承自Exception的抛出信息,至于如何获 得更加详细的JS调试信息,以后JS库中可能会做提供更加详细的调用信息,毕竟框架是在改进中进行的。如下是AjaxApplication类的具体代码:
- public class AjaxApplication
- {
- private AjaxBasePage m_AjaxBasePage;
- private object m_ResponseData;
- public AjaxApplication(AjaxBasePage ajaxBasePage, AjaxRequest ajaxRequest)
- {
- this.m_AjaxBasePage = ajaxBasePage;
- Type ajaxBasePageType = ajaxBasePage.GetType();
- MethodInfo methodInfo = ajaxBasePageType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
- .FirstOrDefault(item => item.Name == ajaxRequest.MethodName);
- object[] parameterData = this.GetParameterData(ajaxRequest, methodInfo);
- if (methodInfo.IsStatic)
- {
- this.m_ResponseData = methodInfo.Invoke(null, parameterData);
- }
- else
- {
- this.m_ResponseData = methodInfo.Invoke(ajaxBasePage, parameterData);
- }
- }
- /// <summary>
- /// 获取参数数据。
- /// </summary>
- private object[] GetParameterData(AjaxRequest ajaxRequest, MethodInfo methodInfo)
- {
- if (methodInfo != null)
- {
- ParameterInfo[] parameterInfos = methodInfo.GetParameters();
- if (parameterInfos.Length > 5)
- {
- throw new NotSupportedException("最多支持5个参数");
- }
- if (parameterInfos.Length > ajaxRequest.Parameters.Count)
- {
- throw new ArgumentException("缺少参数!");
- }
- List<object> parameterData = new List<object>(parameterInfos.Length);
- for (int i = 0; i < parameterInfos.Length; i++)
- {
- ParameterInfo parameterInfo = parameterInfos[i];
- string paramValue = ajaxRequest.Parameters[i];
- try
- {
- parameterData.Add(ParseAjaxParameter(paramValue, parameterInfo));
- }
- catch (FormatException)
- {
- string format = string.Format("传入静态方法 {0} 的第 {1} 个(从0开始计数)参数类型不匹配,应该为 {2} 类型 请检查!", methodInfo.Name, i, parameterInfo.ParameterType.Name);
- throw new FormatException(format);
- }
- }
- return parameterData.ToArray();
- }
- else
- {
- throw new InvalidOperationException("没有发现此方法,请检查该方法签名(方法必须为public)");
- }
- }
- /// <summary>
- /// 类型转换。支持 String、Boolean、Int32、Int64、UInt32、UInt64、Single、Double、Decimal、DateTime、DateTimeOffset、TimeSpan、Guid
- /// </summary>
- private object ParseAjaxParameter(string ajaxParameterValue, ParameterInfo parameterInfo)
- {
- object obj;
- if (parameterInfo.ParameterType == typeof(String))
- {
- obj = ajaxParameterValue;
- }
- else if (parameterInfo.ParameterType == typeof(Boolean))
- {
- obj = bool.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(Int32))
- {
- obj = Int32.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(UInt32))
- {
- obj = UInt32.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(UInt64))
- {
- obj = UInt64.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(Single))
- {
- obj = Single.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(Double))
- {
- obj = Double.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(Decimal))
- {
- obj = Decimal.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(DateTime))
- {
- obj = DateTime.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(DateTimeOffset))
- {
- obj = DateTimeOffset.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(TimeSpan))
- {
- obj = TimeSpan.Parse(ajaxParameterValue);
- }
- else if (parameterInfo.ParameterType == typeof(Guid))
- {
- obj = Guid.Parse(ajaxParameterValue);
- }
- else
- {
- throw new NotSupportedException("方法参数类型不支持!");
- }
- return obj;
- }
- /// <summary>
- /// 结束页面生命周期,同时直接执行应用程序生命周期的EndRequest事件。
- /// </summary>
- public void EndRequest()
- {
- HttpResponse response = this.m_AjaxBasePage.Page.Response;
- response.ContentType = "application/json";
- response.Clear();
- JavaScriptSerializer jsonSerializer2 = new JavaScriptSerializer();
- response.Write(jsonSerializer2.Serialize(new JsonResponse { IsSuccess = true, Message = "处理成功", ResponseData = this.m_ResponseData }));
- response.End();
- }
- }
当初始化了一个AjaxApplication实例后, 可以调用该实例的EndRequest()方法,来结束Ajax请求。该方法内部最后调用Response.End()方法来结束页面生命周期和大部分管线事件。
并用JsonResponse类来封装返回数据。
- public class JsonResponse
- {
- public bool IsSuccess { get; set; }
- public string Message { get; set; }
- public object ResponseData { get; set; }
- }
该类最后一个参数即承载了调用方法的返回值,为一个Object类型,也就是说,框架可以支持任何类型的返回值,当然该类型可以被序列化。
7. 回过头来再看Ajax请求,针对返回值可以这样用:
- PowerAjax.AsyncAjax('TestAjaxMethod', [1, 2, "333", "sss"], function (SucceessResponse) {
- if (SucceessResponse.IsSuceess) {
- alert("恭喜,该ajax方法调用成功!");
- Process(SucceessResponse.ResponseData); // 处理返回的数据,这里可能需要你自己实现了,因为我无法判断你要返回的是什么东西,这是个Object
- } else {
- alert("这是操作错误奥,不是内部异常,内部异常的抛出会我内部会处理的!");
- alert("错误信息:" + SucceessResponse.Message);
- }
- });
以上是试水的东西,希望各位大牛指正。
原文链接: