科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件深度解析ASP.NET2.0中的Callback机制

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在本文中,Teddy将和您一起解析callback的整个调用、反馈机制,相信对于帮助您更好的使用callback,将能有一定的益处。

作者:teddyma 来源:博客园 2007年11月7日

关键字: Windows

  • 评论
  • 分享微博
  • 分享邮件
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方式的控件混合使用,我可以跟您说,会有很多问题。不信你自己可以试试。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章