<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Ajax框架原理分析之Ext.Net

        Ext.Net也是一個很有名的前端框架,它構(gòu)建于ExtJS之上,提供了一整套UI+AJAX的解決方案.通過對其源碼的研究,了解其是如何實現(xiàn)這套AJAX的,對我們也是很有幫助的.

        1.靜態(tài)的AJAX方法實現(xiàn).

        當把[DirectMethod]標記標在一個靜態(tài)方法上時,Ext.Net是通過HttpModule來截獲Http請求實現(xiàn)的.具體的實現(xiàn)類為:DirectRequestModule類

        在應用程序生命周期的PostAcquireRequestState事件內(nèi)中加入處理函數(shù)


      public void Init(HttpApplication app)
      {
          app.PostAcquireRequestState 
      += OnPostAcquireRequestState;
          app.PreSendRequestHeaders 
      += RedirectPreSendRequestHeaders;
      }


        如果是AJAX請求且是靜態(tài)AJAX方法則調(diào)用ProcessRequest方法

      代碼
      private void OnPostAcquireRequestState(object sender, EventArgs eventArgs)
      {
          HttpApplication app 
      = (HttpApplication)sender;
          HttpRequest request 
      = app.Context.Request;

          
      if (RequestManager.IsAjaxRequest)
          {
              
      if (DirectMethod.IsStaticMethodRequest(request) /*|| Utilities.ReflectionUtils.IsTypeOf(app.Context.Handler, "System.Web.Script.Services.ScriptHandlerFactory+HandlerWrapper")*/)
              {
                  
      this.ProcessRequest(app, request);
              }
          }
      }


         通過反射來調(diào)用方法,并結(jié)束服務器處理過程,將結(jié)果返回到客戶端(有刪節(jié))

      代碼
      // Get handler
      HandlerMethods handler = HandlerMethods.GetHandlerMethods(context, request.FilePath);


      // Get method name to invoke
      string methodName = HandlerMethods.GetMethodName(context);

      DirectMethod directMethod 
      = handler.GetStaticMethod(methodName);

      object result = directMethod.Invoke();

      app.Context.Response.Clear();
      app.Context.Response.ClearContent();
      app.Context.Response.ClearHeaders();
      app.Context.Response.StatusCode 
      = 200;
      app.Context.Response.ContentType 
      = "application/json";
      app.Context.Response.Charset 
      = "utf-8";
      app.Context.Response.Cache.SetNoServerCaching();
      app.Context.Response.Cache.SetMaxAge(TimeSpan.Zero);
      app.Context.Response.Write(responseObject.ToString());
      app.CompleteRequest();


        因為是直接通過反射來實現(xiàn),沒有執(zhí)行頁面的生命周期,所以Ext.Net官方推薦此種編寫方式.

       

        2.實例的AJAX方法實現(xiàn).

        我們要重點關注ResourceManager類,它是整個AJAX請求的核心

        首先我們來看是如何實現(xiàn)AJAX方法的調(diào)動.

        當客戶端發(fā)起一個AJAX請求時,Ext.Net會在POST數(shù)據(jù)中加入以下兩個鍵值對:

        __EVENTARGUMENT:btnOK|event|Click

        __EVENTVALIDATION:ResourceManager1

        表示由ResourceManager類型的ResourceManager1實例來處理這次AJAX請求.具體發(fā)起請求的按鈕是btnOK,形式為事件,方式為Click.

        在ResourceManager類的OnLoad事件中,如果是AJAX請求,則在LoadComplete事件中加入Page_AjaxLoadComplete處理函數(shù)

      代碼
      protected override void OnLoad(EventArgs e)
      {
          
      base.OnLoad(e);

          
      if (RequestManager.IsAjaxRequest && !this.Page.IsPostBack && !this.IsDynamic)
          {
              
      this.Page.LoadComplete += Page_AjaxLoadComplete;
          }
      }


        在Page_AjaxLoadComplete處理函數(shù)中,借用回發(fā)的處理方法來實現(xiàn)AJAX調(diào)用:

      代碼
      string _ea = this.Page.Request["__EVENTARGUMENT"];

      if (_ea.IsNotEmpty())
      {
          
      string _et = this.Page.Request["__EVENTTARGET"];

          
      if (_et == this.UniqueID)
          {
              
      this.RaisePostBackEvent(_ea);
          }

          
      return;
      }


        在RaisePostBackEvent方法中,實現(xiàn)對具體控件具體方法的具體調(diào)用:

      代碼
      string controlID = args[0];
      string controlEvent = args[2];

      ctrl 
      = ControlUtils.FindControlByClientID(this.Page, controlID, truenull);

      case AjaxRequestType.Event:
          Observable observable 
      = ctrl as Observable;

          
      if (observable == null)
          {
              
      if (ctrl is ResourceManagerProxy)
              {
                  ((ResourceManagerProxy)ctrl).FireAsyncEvent(controlEvent, extraParams);
              }
              
      else if (ctrl is ResourceManager)
              {
                  
      this.FireAsyncEvent(controlEvent, extraParams);
              }
              
      else
              {
                  
      throw new HttpException("The control with ID '{0}' is not Observable".FormatWith(controlID));
              }
          }
          
          
      if (observable != null)
          {
              observable.FireAsyncEvent(controlEvent, extraParams);
          }
          
      break;


        然后我們來看Ext.Net是如何將處理結(jié)果返回給客戶端的.

        (29日繼續(xù))

        首先我們要明白一點,后臺的Ext.Net控件在輸出到客戶端的并不是HTML代碼,而是JSON包裝后的JS代碼。瀏覽器執(zhí)行接收到的JS代碼后再生成HTML代碼。

        我們知道,控件的輸出一般都寫在生命周期的Render事件中。XControl是所有Ext.Net控件的基類。這個類比較大,作者用了近十個文件,采用分部類的開發(fā)方式來實現(xiàn)這個類。Lifecycle.cs文件主要負責重寫控件的生命周期。在其重寫的Render中,調(diào)用了HtmlRender方法。此方法是一般的具體控件的實際輸出方法。另外在ResourceManager類的RenderAction方法中輸出頁面腳本注冊,樣式注冊,頁面初始化腳本等等。這些輸出不是單純的輸出HTML或JS代碼,而是在輸出的內(nèi)容的兩端加上了類似于“<Ext.Net.Direct.Response>”的標簽,這是為下一步輸出過濾做準備。

        接著就要看輸出過濾了。我們知道,傳統(tǒng)的Asp.Net提交,服務器會完成整個頁面的生命周期,之后將處理過后的整個頁面的內(nèi)容返回。但是Ext.Net的AJAX提交走完了整個頁面的生命周期,返回的卻是Json數(shù)據(jù)。這其中倒底有什么玄機?答案就在輸出過濾!(光尋找這一點我就花了近三個小時,原因是我在聽WebCast的的時候,老趙說Asp.net Ajax框架是在Render事件上做手腳,對內(nèi)容進行了重輸出,我想Ext.Net應該差不多,于是使勁找,結(jié)果什么也找不到。  —_—!)

        

        還是在DirectRequestModule類中:

      public void Init(HttpApplication app)
      {
          app.ReleaseRequestState += AjaxRequestFilter;
      }

       

        一開始我以為沒什么用,現(xiàn)在才知道這是處理AJAX返回數(shù)據(jù)的關鍵!

      代碼
      HttpResponse response = HttpContext.Current.Response;

      if (RequestManager.IsAjaxRequest)
      {
          
      if (response.ContentType.IsNotEmpty() && response.ContentType.Equals("text/html", StringComparison.InvariantCultureIgnoreCase))
          {
              response.Filter = new AjaxRequestFilter(response.Filter);
          }
      }


        在這里,AjaxRequestFilter類是主要實現(xiàn)類。其Flush方法是關鍵方法。 里面用到的DirectResponse類是返回的包裝類,將可能的返回信息封裝成了一個類,我們一步一步的看。

       

      string raw = this.html.ToString();

      StringBuilder buffer 
      = new StringBuilder(256);

      DirectResponse ajaxResponse 
      = new DirectResponse(true);
      HttpContext context 
      = HttpContext.Current;

      這里是一些初始化的工作。其中html就是待過濾的原始的html代碼。

       

      object isUpdate = context.Items["Ext.Net.Direct.Update"];

      if (isUpdate != null && (bool)isUpdate)
      {
          
      this.ExtractUpdates(raw, ref buffer);
      }

      這里是從原始html提取更新的部份并寫到buffer中去。思路是用正則去匹配的,具體實現(xiàn)自行看代碼!

       

      代碼
      string dynamicHtml = this.ExtractDynamicHtml(raw);

      object isManual = context.Items["Ext.Net.Direct.Response.Manual"];

      if (isManual != null && (bool)isManual)
      {
          
      if (raw.StartsWith("<Ext.Net.Direct.Response.Manual>"))
          {
              
      string script = dynamicHtml.ConcatWith(raw.RightOf("<Ext.Net.Direct.Response.Manual>").LeftOf("</Ext.Net.Direct.Response.Manual>"));
              
      byte[] rsp = System.Text.Encoding.UTF8.GetBytes(script);
              
      this.response.Write(rsp, 0, rsp.Length);
              
      this.response.Flush();
              
      return;
          }
      }

      buffer.Append(dynamicHtml);

      這里是從原始的html提取動態(tài)生成的html代碼,這里有個小插曲,如果isManual與raw滿意要求的話,就直接將提取的結(jié)果返回了。否則也將結(jié)果寫到buffer中。

       

      代碼
      string error = context == null ? null : (context.Error != null ? context.Error.ToString() : null);

      if (!ResourceManager.AjaxSuccess || error.IsNotEmpty())
      {
          ajaxResponse.Success 
      = false;

          
      if (error.IsNotEmpty())
          {
              ajaxResponse.ErrorMessage 
      = error; 
          }
          
      else
          {
              ajaxResponse.ErrorMessage 
      = ResourceManager.AjaxErrorMessage; 
          }
      }

      這里是錯誤處理,就不多說了。

       

      代碼
      if (ResourceManager.ReturnViewState)
                      {
                          ajaxResponse.ViewState 
      = AjaxRequestFilter.GetHiddenInputValue(raw, BaseFilter.VIEWSTATE);
                          ajaxResponse.ViewStateEncrypted 
      = AjaxRequestFilter.GetHiddenInputValue(raw, BaseFilter.VIEWSTATEENCRYPTED);
                          ajaxResponse.EventValidation 
      = AjaxRequestFilter.GetHiddenInputValue(raw, BaseFilter.EVENTVALIDATION);
                      }

      這里是從原始的html提取ViewState

       

      代碼
      object obj = ResourceManager.ServiceResponse;

      if (obj is Response)
      {
          ajaxResponse.ServiceResponse 
      = new ClientConfig().Serialize(obj);
      }
      else
      {
          ajaxResponse.ServiceResponse 
      = obj != null ? JSON.Serialize(obj) : null;
      }

      if (ResourceManager.ExtraParamsResponse.Count > 0)
      {
          ajaxResponse.ExtraParamsResponse 
      = ResourceManager.ExtraParamsResponse.ToJson();
      }

      if (ResourceManager.DirectMethodResult != null)
      {
          ajaxResponse.Result 
      = ResourceManager.DirectMethodResult;
      }

      這里是從ResourceManager類中獲取指定數(shù)據(jù)。

       

      buffer.Append(raw.RightOf("<Ext.Net.Direct.Response>").LeftOf("</Ext.Net.Direct.Response>"));

      if (buffer.Length > 0)
      {
          ajaxResponse.Script 
      = "<string>".ConcatWith(buffer.ToString());
      }

      這里是從原始的html提取被"<Ext.Net.Direct.Response>"標記的內(nèi)容。寫到buffer中,并終賦到ajaxResponse.Script屬性中。

       

      代碼
      byte[] data = System.Text.Encoding.UTF8.GetBytes((isUpload ? "<textarea>" : ""+ ajaxResponse.ToString() + (isUpload ? "</textarea>" : "") );
      this.response.Write(data, 0, data.Length);

      this.response.Flush();

      最后,將結(jié)果通過DirectResponse類重寫過的ToString方法將結(jié)果序列化輸出到客戶端。


        總結(jié)輸出的過程,其實是從原始的HTML代碼提取出相關信息填充到DirectResponse類的相關屬性中,再將其序列化到客戶端的過程。從ResourceManager獲取ServiceResponse,ExtraParamsResponse,Result,從原始HTML獲取ViewState,ViewStateEncrypted,EventValidation,從原始HTML獲取更新的數(shù)據(jù),動態(tài)的HTML內(nèi)容,"<Ext.Net.Direct.Response>"并填入Script屬性,跟據(jù)需要設置Success與ErrorMessage屬性。通過重寫DirectResponse類的ToString方法,來實現(xiàn)序列化過程。

        以上就是我的分析。可能非常的粗枝大葉,但整個流程的基本架構(gòu)是分析出來了。 雖然代碼具體實現(xiàn)的好壞可能仁者見仁,智者見智,但里面真的還是有很多東西值得我去學習的!

      posted @ 2010-11-26 10:55  永遠的阿哲  閱讀(2614)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 亚洲国产精品美日韩久久| 97精品尹人久久大香线蕉| 成年女人午夜毛片免费视频| 久久精品熟妇丰满人妻久久| 亚洲日韩精品无码一区二区三区 | 国产99视频精品免费视频36| 久久99日韩国产精品久久99| 色AV专区无码影音先锋| 日本新janpanese乱熟| 久久精品青青大伊人av| 中文字幕国产精品第一页| 一区二区丝袜美腿视频| 欧美老少配性行为| 九色综合国产一区二区三区| 国产免费久久精品44| 欧美一区二区三区成人久久片| 色综合色综合久久综合频道| 亚洲成A人片在线观看无码不卡| 亚洲综合色婷婷中文字幕| 国产日本一区二区三区久久| 亚洲国产精品人人做人人爱| 日本亚洲色大成网站www久久 | 鲁一鲁一鲁一鲁一澡| 欧美情侣性视频| 老色鬼永久精品网站| 麻豆亚洲精品一区二区| 欧美高清精品一区二区| 国内自拍第一区二区三区| 中文字幕人妻在线精品| 亚洲精品久久久久国色天香 | 午夜在线欧美蜜桃| 国产精品原创不卡在线| 国产一区| 亚洲av成人一区在线| 国产精品99久久久久久董美香 | 亚洲αⅴ无码乱码在线观看性色| 亚洲男人AV天堂午夜在| 婷婷六月天在线| 国产成人久久精品一区二区| 国产女人18毛片水真多1| 口爆少妇在线视频免费观看|