正 文

深度解析ASP.NET2.0中的Callback机制


www.7dspace.com  更新日期:2005-12-1 3:01:20  七度空间


  Serverside Callback Operation & Render

  好了,那么接下来就让我们来看看在服务端,ASP.NET都为我们做了些什么。

  首先,我们知道,当前的Page是必须实现ICallbackEventHandler这个接口的,也就是其包含的两个函数:string GetCallbackResult()和void RaiseCallbackEvent(eventArgument)。根据MSDN的文档,我们知道,在一个callback被post到服务端时, Page将会首先将post回来的form data绑定到当前页面的服务端web控件,接着判断本次post是callback还是postback,如果是postpost,那么自然是原来的那个机制;

  如果是callback,则将回调用触发本次callback的控件(在本例中,我们在激发这个callback时,第一个参数指定的是this也就是当前的Page,那么这里当前的Page就是这个触发控件)的RaiseCallbackEvent (eventArgument),当然,eventArgument也将会正确的传过来,在这个函数的实现代码里我们可以对这个参数进行解析处理,并在某个地方,存储我们准备返回的数据,或者待处理的已经被解析出来的参数。

  接着,系统将调用string GetCallbackResult(),在这个函数的实现代码中,我们可以直接返回我们在RaiseCallback函数中存储的准备返回的数据,或者根据待处理的已经被解析出来的参数处理这些参数,并返回结果。这个返回的字符串,自然将以脚本的形式被render回客户端。被返回的脚本细节如下(反编译Page.RenderCallback()的源码),我们可以看到,返回的结果除了我们需要的结果数据和相应的脚本,没有多余的数据,因此, callback的执行效率应该说还是不错的:

private void RenderCallback()
{
 bool flag1 = !string.IsNullOrEmpty(this._requestValueCollection["__CALLBACKLOADSCRIPT"]);
 try
 {
  string text1 = null;
  if (flag1)
  {
   text1 = this._requestValueCollection["__CALLBACKINDEX"];
   if (string.IsNullOrEmpty(text1))
   {
    throw new HttpException(SR.GetString("Page_CallBackInvalid"));
   }
   for (int num1 = 0; num1 < text1.Length; num1++)
   {
    if (!char.IsDigit(text1, num1))
    {
     throw new HttpException(SR.GetString("Page_CallBackInvalid"));
    }
   }
   this.Response.Write("<script>parent.__pendingCallbacks[");
   this.Response.Write(text1);
   this.Response.Write("].xmlRequest.responseText=\"");
  }
  if (this._callbackControl != null)
  {
   string text2 = this._callbackControl.GetCallbackResult();
   if (this.EnableEventValidation)
   {
    string text3 = this.ClientScript.GetEventValidationFieldValue();
    this.Response.Write(text3.Length.ToString(CultureInfo.InvariantCulture));
    this.Response.Write('|');
    this.Response.Write(text3);
   }
   else
   {
    this.Response.Write('s');
   }
   this.Response.Write(flag1 ? Util.QuoteJScriptString(text2) : text2);
  }
  if (flag1)
  {
   this.Response.Write("\";parent.__pendingCallbacks[");
   this.Response.Write(text1);
   this.Response.Write("].xmlRequest.readyState=4;parent.WebForm_CallbackComplete();</script>");
  }
 }
 catch (Exception exception1)
 {
  this.Response.Clear();
  this.Response.Write('e');
  if (this.Context.IsCustomErrorEnabled)
  {
   this.Response.Write(SR.GetString("Page_CallBackError"));
   return;
  }
  this.Response.Write(flag1 ? Util.QuoteJScriptString(HttpUtility.HtmlEncode(exception1.Message)) :  HttpUtility.HtmlEncode(exception1.Message));
 }
}

  另外,才发现原来System.Web.UI.Utils这个类中有那么多有用的方便的函数如QuateJScriptString(),以前一直自己手写这样功能的函数呢~~真傻呀~~

  Conclusion

  至此,我们已经基本上清楚明白callback的前台幕后了。如果您对服务段的处理过程的细节还觉得不够,您也可以自行反编译Page对象,看看其实现代码的细节,还是很有意思的。

  总体而言,我们发现,callback无论是兼容性(XMLHTTP或IFRAME我想大多数浏览器都支持吧),还是性能(没有返回不需要的数据),还是使用的便利性(因为ASP.NET帮我们绑定了页面上的当前的Web控件的数据,这就意味着我们可以在callback后的服务端,象postback 时一样来写代码,也方便我们移植原来的postback的代码到callback方式的代码)都是非常优秀的。我们也完全可以扩展现有的控件,或者写我们自己的控件以支持这样的callback效果,并且,混合使用callback控件和原来的postback方式的控件也是非常可靠和容易的。这对我们升级原来的基于postback为主的代码,是非常有利的,如果用Atlas来做同样的代码升级和与postback方式的控件混合使用,我可以跟您说,会有很多问题。不信你自己可以试试。

3页,页码:[1] [2] [3] 

上一篇:网管员必读 10分钟恢复网络服务有绝招
下一篇:ASP.NET中随机数生成及应用
作者:teddyma  来源:博客园 ( 责任编辑:7dspace )
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐