您好,登錄后才能下訂單哦!
這篇文章主要講解了“ASP.NET WebForm中怎么使用Ajax”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“ASP.NET WebForm中怎么使用Ajax”吧!
對于asp.net WebForm項目,進行Ajax操作大概有三種方式:web服務(.asmx文件) , 一般處理程序(.ashx)和 一些Ajax控件。
對于.net提供的ajax控件,暫且不說,只說另外兩種方式,都需要引入額外的代碼文件對Ajax進行操作(asmx和ashx,且web服務還要引入一個cs文件與之對應),假如要對Example.aspx這個頁面添加一些自定義的Ajax操作,并且這些Ajax操作并不會在別的頁面上用到,如此不得不引入額外的代碼文件完成這個操作,假如這個Ajax操作很簡單,只需要一個簡單的函數就可以執行,那豈不是很麻煩的過程嗎?如此一來,隨著項目中 Ajax操作的增多,ashx和asmx文件都會隨著時間的增長而增長,項目的維護也會隨之加倍。為什么我們不能把Ajax操作的后臺代碼直接放在 Example.aspx對應的Example.aspx.cs文件里 ? 如果能這樣做,以上兩種煩惱都會迎刃而解,不是嗎?
于是,按照以上思路,實現了如下Ajax框架。先來看這個框架的實現機制:
上圖是自己畫的一個縮減版IIS接收到一個aspx請求的HttpApplication管線和asp.net Page在執行ProcessRequest()方法中的頁面生命周期的部分事件。Page本身是繼承自IHttpHandler接口,IHttpHandler提供了一個重要的約束方法ProcessRequest,該方法是對接收到的信息(HttpContext)進行具體的處理同樣,一般處理程序和web服務也實現了自己的IHttpHandler,并以此提供一些Ajax服務。具體的操作過程請自行查找MSDN。
原理是在頁面生命周期開始的第一個事件PreInit進行一些處理,一旦發現劫持到的請求是一個ajax請求,那么利用C#的反射來調用aspx.cs中定義的方法,執行完方法之后,調用Response.End()方法,調用這個方法會直接跳到管線的EndRequest事件,從而結束請求,這樣就無需走一些沒有必要的頁面生命周期的步驟,從而完成一個Ajax操作。如果發現是一個正常的操作,那么就走正常流程。
下面以一個簡單例子說明該Ajax框架的使用:
1. 添加一個解決方案
2. 新建一個 Default.aspx 頁面
3. 在Default.aspx.cs頁面中創建一個被調用的測試方法:
public List<string> TestAjaxMethod(int a, string b, float c) { return new List<string> { a.ToString(), b, c.ToString() }; }
4. 在Default.aspx中寫一個Ajax請求
PowerAjax.AsyncAjax(‘TestAjaxMethod’, [1, 2, "333","sss"], function (SucceessResponse) { // 成功后的代碼 });
PowerAjax.js是用Jquery專門為這個框架封裝的一個及其簡單的JS類庫,這個類庫中有兩個主要的方法:PowerAjax.AsyncAjax和PowerAjax.SyncAjax,一個提供同步操作,一個提供異步操作,參數有三個:
第一個參數是即將操作在aspx.cs的Ajax方法的名字(用名字反射方法)。
第二個參數是一個以數組形式組成參數列表數據。
第三個參數是操作成功之后執行執行的回調方法,與c#中的委托一個道理。
以下為這個簡單JS庫的代碼:
var PowerAjax = function () { } PowerAjax.__Private = function () { } // 進行異步操作 PowerAjax.AsyncAjax = function (methodName, paramArray, success) { PowerAjax.__Private.Ajax(methodName, paramArray, success, true); } // 進行的是同步操作 PowerAjax.SyncAjax = function (methodName, paramArray, success) { PowerAjax.__Private.Ajax(methodName, paramArray, success, false); } PowerAjax.__Private.Ajax = function (methodName, paramArray, success, isAsync) { var data = {}; switch (paramArray.length) { case 0: data = { 'isAjaxRequest': true, 'MethodName': methodName }; break; case 1: data = { 'isAjaxRequest': true, 'MethodName': methodName, "param0": paramArray[0] }; break; case 2: data = { 'isAjaxRequest': true, 'MethodName': methodName, "param0": paramArray[0], "param1": paramArray[1] }; break; case 3: data = { 'isAjaxRequest': true, 'MethodName': methodName, "param0": paramArray[0], "param1": paramArray[1], "param2": paramArray[2] }; break; case 4: data = { 'isAjaxRequest': true, 'MethodName': methodName, "param0": paramArray[0], "param1": paramArray[1], "param2": paramArray[2], "param3": paramArray[3] }; break; case 5: data = { 'isAjaxRequest': true, 'MethodName': methodName, "param0": paramArray[0], "param1": paramArray[1], "param2": paramArray[2], "param3": paramArray[3], "param4": paramArray[4] }; break; } var url = document.location.href; $.ajax({ type: "post", url: url, data: data, async: isAsync, datatype: "json", contentType: "application/x-www-form-urlencoded; charset=UTF-8", success: function (response) { success(response); }, error: function (response) { if (response.status == 500) { var errorMessage = response.responseText; var errorTitle = errorMessage.substring(errorMessage.indexOf("<title>") + 7, errorMessage.indexOf("</title>")) throw new Error("服務器內部錯誤:" + errorTitle); } } }); }
5. 更改Default.aspx.cs的繼承頁面為AjaxBasePage
public partial class _Default : AjaxBasePage
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); } });
感謝各位的閱讀,以上就是“ASP.NET WebForm中怎么使用Ajax”的內容了,經過本文的學習后,相信大家對ASP.NET WebForm中怎么使用Ajax這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。