溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ASP.NET WebForm中怎么使用Ajax

發(fā)布時(shí)間:2021-12-06 15:21:00 來源:億速云 閱讀:218 作者:iii 欄目:編程語言

這篇文章主要講解了“ASP.NET WebForm中怎么使用Ajax”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“ASP.NET WebForm中怎么使用Ajax”吧!

對于asp.net WebForm項(xiàng)目,進(jìn)行Ajax操作大概有三種方式:web服務(wù)(.asmx文件)  ,  一般處理程序(.ashx)和  一些Ajax控件。

對于.net提供的ajax控件,暫且不說,只說另外兩種方式,都需要引入額外的代碼文件對Ajax進(jìn)行操作(asmx和ashx,且web服務(wù)還要引入一個(gè)cs文件與之對應(yīng)),假如要對Example.aspx這個(gè)頁面添加一些自定義的Ajax操作,并且這些Ajax操作并不會(huì)在別的頁面上用到,如此不得不引入額外的代碼文件完成這個(gè)操作,假如這個(gè)Ajax操作很簡單,只需要一個(gè)簡單的函數(shù)就可以執(zhí)行,那豈不是很麻煩的過程嗎?如此一來,隨著項(xiàng)目中 Ajax操作的增多,ashx和asmx文件都會(huì)隨著時(shí)間的增長而增長,項(xiàng)目的維護(hù)也會(huì)隨之加倍。為什么我們不能把Ajax操作的后臺(tái)代碼直接放在 Example.aspx對應(yīng)的Example.aspx.cs文件里 ? 如果能這樣做,以上兩種煩惱都會(huì)迎刃而解,不是嗎?

于是,按照以上思路,實(shí)現(xiàn)了如下Ajax框架。先來看這個(gè)框架的實(shí)現(xiàn)機(jī)制:

ASP.NET WebForm中怎么使用Ajax

上圖是自己畫的一個(gè)縮減版IIS接收到一個(gè)aspx請求的HttpApplication管線和asp.net Page在執(zhí)行ProcessRequest()方法中的頁面生命周期的部分事件。Page本身是繼承自IHttpHandler接口,IHttpHandler提供了一個(gè)重要的約束方法ProcessRequest,該方法是對接收到的信息(HttpContext)進(jìn)行具體的處理同樣,一般處理程序和web服務(wù)也實(shí)現(xiàn)了自己的IHttpHandler,并以此提供一些Ajax服務(wù)。具體的操作過程請自行查找MSDN。

原理是在頁面生命周期開始的第一個(gè)事件PreInit進(jìn)行一些處理,一旦發(fā)現(xiàn)劫持到的請求是一個(gè)ajax請求,那么利用C#的反射來調(diào)用aspx.cs中定義的方法,執(zhí)行完方法之后,調(diào)用Response.End()方法,調(diào)用這個(gè)方法會(huì)直接跳到管線的EndRequest事件,從而結(jié)束請求,這樣就無需走一些沒有必要的頁面生命周期的步驟,從而完成一個(gè)Ajax操作。如果發(fā)現(xiàn)是一個(gè)正常的操作,那么就走正常流程。

下面以一個(gè)簡單例子說明該Ajax框架的使用:

1. 添加一個(gè)解決方案

2. 新建一個(gè) Default.aspx 頁面

3. 在Default.aspx.cs頁面中創(chuàng)建一個(gè)被調(diào)用的測試方法:

public List<string>  TestAjaxMethod(int a, string b, float c)          {                 return new List<string> { a.ToString(), b, c.ToString() };          }

4.      在Default.aspx中寫一個(gè)Ajax請求

PowerAjax.AsyncAjax(&lsquo;TestAjaxMethod&rsquo;, [1, 2, "333","sss"], function (SucceessResponse) {          // 成功后的代碼  });

PowerAjax.js是用Jquery專門為這個(gè)框架封裝的一個(gè)及其簡單的JS類庫,這個(gè)類庫中有兩個(gè)主要的方法:PowerAjax.AsyncAjax和PowerAjax.SyncAjax,一個(gè)提供同步操作,一個(gè)提供異步操作,參數(shù)有三個(gè):

第一個(gè)參數(shù)是即將操作在aspx.cs的Ajax方法的名字(用名字反射方法)。

第二個(gè)參數(shù)是一個(gè)以數(shù)組形式組成參數(shù)列表數(shù)據(jù)。

第三個(gè)參數(shù)是操作成功之后執(zhí)行執(zhí)行的回調(diào)方法,與c#中的委托一個(gè)道理。

以下為這個(gè)簡單JS庫的代碼:

var PowerAjax = function () { }  PowerAjax.__Private = function () { }     // 進(jìn)行異步操作  PowerAjax.AsyncAjax = function (methodName, paramArray, success) {      PowerAjax.__Private.Ajax(methodName, paramArray, success, true);  }     // 進(jìn)行的是同步操作  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("服務(wù)器內(nèi)部錯(cuò)誤:" + errorTitle);              }          }      });  }

5. 更改Default.aspx.cs的繼承頁面為AjaxBasePage              

public partial class _Default : AjaxBasePage

6. 主要基類:AjaxBasePage類

如下代碼:

public class AjaxBasePage : System.Web.UI.Page  {      /// <summary>      /// 是否是一個(gè)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請求,繼續(xù)執(zhí)行頁面生命周期的剩余事件              base.OnPreInit(e);          }      }  }

該類重寫了PreInit方法,判斷請求是否是一個(gè)Ajax請求。通過AjaxRequest類接收并處理接收到的請求,提取出一些有效的數(shù)據(jù),比如說是否是一個(gè)Ajax請求,方法的名字,參數(shù)列表(AjaxParameter類)。

至于AjaxParameter類,內(nèi)部用的數(shù)據(jù)結(jié)構(gòu)其實(shí)是一個(gè)字典,并使用索引來提供對數(shù)據(jù)的方便訪問,提供一個(gè)Count屬性,方便獲取參數(shù)的個(gè)數(shù)。     如下代碼

public class AjaxParameter      {          private IDictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();             /// <summary>          /// 返回參數(shù)的個(gè)數(shù)。          /// </summary>          public int Count          {              get              {                  return this.m_DictionaryParamsData.Count;              }          }             /// <summary>          /// 索引具體參數(shù)的值。          /// </summary>          /// <param name="index"></param>          /// <returns></returns>          public string this[int index]          {              get              {                  if (index >= 5 || index < 0)                  {                      throw new NotSupportedException("請求方法的參數(shù)的個(gè)數(shù)限制為:0-5");                  }                  return this.m_DictionaryParamsData[index];              }          }             public AjaxParameter(IDictionary<int, string> paramsData)          {              this.m_DictionaryParamsData = paramsData;          }      }

AjaxRequest類的設(shè)計(jì)思路其實(shí)是模仿HttpContext設(shè)計(jì),HttpContext能夠從基礎(chǔ)的http請求報(bào)文分析出以后處理將要用到的數(shù)據(jù)(response,request,session,cookie等等)數(shù)據(jù),而AjaxRequest通過分析Ajax的Post請求的數(shù)據(jù)域 Data分析出各種以后會(huì)用到的數(shù)據(jù)。如下是該類的代碼:

public class AjaxRequest      {          private Dictionary<int, string> m_DictionaryParamsData = new Dictionary<int, string>();          private AjaxParameter m_AjaxParameter;          private int m_Count = 0;             #region 屬性          /// <summary>          /// 是否是一個(gè)Ajax請求。          /// </summary>          public bool IsAjaxRequest { get; private set; }             /// <summary>          /// 請求的方法名字。          /// </summary>          public string MethodName { get; private set; }             /// <summary>          /// 參數(shù)數(shù)據(jù)。          /// </summary>          public AjaxParameter Parameters          {              get { return this.m_AjaxParameter; }          }          #endregion             #region 構(gòu)造函數(shù)          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 實(shí)例方法          public static AjaxRequest GetInstance(NameValueCollection nameValueCollection)          {              return new AjaxRequest(nameValueCollection);          }          #endregion             #region ToString          public override string ToString()          {              return this.MethodName;          }          #endregion      }

通過分析AjaxRequest的屬性IsAjaxRequest可判斷是否為Ajax請求,若該請求為一個(gè)Ajax請求,那么創(chuàng)建一個(gè)AjaxApplication實(shí)例,在創(chuàng)建AjaxApplication實(shí)例的過程中會(huì)利用當(dāng)前頁面和AjaxRequest提供的數(shù)據(jù)進(jìn)行實(shí)際方法的調(diào)用(反射),該類是執(zhí)行Ajax方法的核心類,其中會(huì)判斷是否讀取的到的方法是一個(gè)有效的方法,并判斷從JS中AjaxApplication傳入的參數(shù)類型的有效性,目前只提供對以下13中參數(shù)提供支持,如下:

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

如果方法中出現(xiàn)非以上類型,將會(huì)拋出異常。為了方便Ajax的調(diào)試,在JS前段類庫中我會(huì)對異常進(jìn)行處理,并拋出Error,Error信息有效的截取了繼承自Exception的拋出信息,至于如何獲    得更加詳細(xì)的JS調(diào)試信息,以后JS庫中可能會(huì)做提供更加詳細(xì)的調(diào)用信息,畢竟框架是在改進(jìn)中進(jìn)行的。如下是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>          /// 獲取參數(shù)數(shù)據(jù)。          /// </summary>          private object[] GetParameterData(AjaxRequest ajaxRequest, MethodInfo methodInfo)          {              if (methodInfo != null)              {                  ParameterInfo[] parameterInfos = methodInfo.GetParameters();                     if (parameterInfos.Length > 5)                  {                      throw new NotSupportedException("最多支持5個(gè)參數(shù)");                  }                     if (parameterInfos.Length > ajaxRequest.Parameters.Count)                  {                      throw new ArgumentException("缺少參數(shù)!");                  }                     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("傳入靜態(tài)方法 {0} 的第 {1} 個(gè)(從0開始計(jì)數(shù))參數(shù)類型不匹配,應(yīng)該為 {2} 類型 請檢查!", methodInfo.Name, i, parameterInfo.ParameterType.Name);                          throw new FormatException(format);                      }                  }                  return parameterData.ToArray();              }              else             {                  throw new InvalidOperationException("沒有發(fā)現(xiàn)此方法,請檢查該方法簽名(方法必須為public)");              }          }             /// <summary>          /// 類型轉(zhuǎn)換。支持 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("方法參數(shù)類型不支持!");              }              return obj;          }             /// <summary>          /// 結(jié)束頁面生命周期,同時(shí)直接執(zhí)行應(yīng)用程序生命周期的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();          }      }

當(dāng)初始化了一個(gè)AjaxApplication實(shí)例后, 可以調(diào)用該實(shí)例的EndRequest()方法,來結(jié)束Ajax請求。該方法內(nèi)部最后調(diào)用Response.End()方法來結(jié)束頁面生命周期和大部分管線事件。

并用JsonResponse類來封裝返回?cái)?shù)據(jù)。

public class JsonResponse  {      public bool IsSuccess { get; set; }      public string Message { get; set; }      public object ResponseData { get; set; }  }

該類最后一個(gè)參數(shù)即承載了調(diào)用方法的返回值,為一個(gè)Object類型,也就是說,框架可以支持任何類型的返回值,當(dāng)然該類型可以被序列化。

7. 回過頭來再看Ajax請求,針對返回值可以這樣用:

PowerAjax.AsyncAjax('TestAjaxMethod', [1, 2, "333", "sss"], function (SucceessResponse) {      if (SucceessResponse.IsSuceess) {          alert("恭喜,該ajax方法調(diào)用成功!");          Process(SucceessResponse.ResponseData); // 處理返回的數(shù)據(jù),這里可能需要你自己實(shí)現(xiàn)了,因?yàn)槲覠o法判斷你要返回的是什么東西,這是個(gè)Object      } else {          alert("這是操作錯(cuò)誤奧,不是內(nèi)部異常,內(nèi)部異常的拋出會(huì)我內(nèi)部會(huì)處理的!");          alert("錯(cuò)誤信息:" + SucceessResponse.Message);      }  });

感謝各位的閱讀,以上就是“ASP.NET WebForm中怎么使用Ajax”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對ASP.NET WebForm中怎么使用Ajax這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI