linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘建议留言网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > asp.net >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·NetBPM工作流的一个示例:请假
·asp.net正则表达式语法
·Office Web Components(OWC)绘
·asp.net ajax客户端编程+jquer
·asp.net 2.0 ajax中使用PopupC
·数据源为空时如何让GridView显
·如何让UpdatePanel支持文件上传
·Ado.Net读取Excel常见问题总结
·Brettle.Web.NeatUpload.dll支
·C#.Net的常见面试试题和参考答
·如何使IE的后退按钮无效
·ASP.NET DEMO 15: 同时支持行单
·ASP.NET使用Cookie
·asp.net 2.0 ajax中实现弹出窗
·如何在ASP.NET中用OWC绘制图表
最新文章
·Ajax Control Toolkit Animati
·讨论一下类似BlogEngine内一次
·使用CSS+SiteMap+UserControl+
·Asp.net中多彩下拉框的实现
·浅谈ASP.NET的Postback
·分清ASP.NET AJAX中的Extender
·Tip:在使用AjaxControlTookit
·有关注册DataItem的一些可能被
·IIRF(Ionic's Isapi Rewrite
·asp.net 客户端回调功能的实现
·关于控件部分的看法--读Progra
·为什么在vista上做开发
·如何封装JS和CSS文件为服务器端
·岂今我看过的最强的排序算法
·设计模式学习笔记之单件模式
Google
 
有关注册DataItem的一些可能被忽视的事情
[ 作者:  加入时间:2007-12-28 12:22:12  来自:Linux联盟收集整理 ]
在UpdatePanel对页面进行部分刷新时注册一些Data Item是ASP.NET AJAX的特点之一。我们可以在服务器端为某个控件注册一个字符串甚至是一个对象,然后在客户端将将其取回。但是现在我希望向您展示一些您可能会忽视的事情。 SFFLinux联盟
   SFFLinux联盟
    让我们先从最基本的用法开始。在一个异步回送过程中,我们可以调用RegisterDataItem方法将一个字符串与一个UpdatePanel绑定起来: SFFLinux联盟
   SFFLinux联盟
  RegisterDataItem方法调用 SFFLinux联盟
  ScriptManager.GetCurrent(this.Page).RegisterDataItem(this.UpdatePanel1, "DataItem"); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    在客户端,如果我们监听pageLoading,pageLoaded或者endRequest事件,我们就可以使用下面的代码,使用控件的ClientID将这个字符串取回: SFFLinux联盟
   SFFLinux联盟
  将字符串取回 SFFLinux联盟
  Sys.WebForms.PageRequestManager.getInstance().add_pageLoading( SFFLinux联盟
   function(sender, e) SFFLinux联盟
   { SFFLinux联盟
   var dataItem = e.get_dataItems()["<%= this.UpdatePanel1.ClientID %>"]; // "DataItem" SFFLinux联盟
   // more implementations... SFFLinux联盟
   }); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    RegisterDataItem方法还有一个重载的版本会接受一个额外的参数,其作用是使用一个布尔值来表明我们注册的dataItem是不是已经被序列化为JSON。但是这里就出了一个问题——甚至在官方文档中的示例也是不正确的。 SFFLinux联盟
   SFFLinux联盟
    下面的代码选自官方文档中的示例: SFFLinux联盟
   SFFLinux联盟
  官方文档中的示例 SFFLinux联盟
  protected void Page_Load(object sender, EventArgs e) SFFLinux联盟
  { SFFLinux联盟
   if (ScriptManager1.IsInAsyncPostBack) SFFLinux联盟
   { SFFLinux联盟
   System.Web.Script.Serialization.JavaScriptSerializer json = SFFLinux联盟
   new System.Web.Script.Serialization.JavaScriptSerializer(); SFFLinux联盟
   ScriptManager1.RegisterDataItem(Label1, DateTime.Now.ToString()); SFFLinux联盟
   ScriptManager1.RegisterDataItem(Label2, json.Serialize("more data"), true); SFFLinux联盟
   } SFFLinux联盟
  } SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    这个示例的确能够正常工作,但是它事实上掩盖了一个问题。请注意,序列化之后的Data Item会被JavaScript内置的eval方法解释执行: SFFLinux联盟
   SFFLinux联盟
  使用eval函数解释执行 SFFLinux联盟
  function Sys$WebForms$PageRequestManager$_onFormSubmitCompleted(sender, eventArgs) SFFLinux联盟
  { SFFLinux联盟
   //... SFFLinux联盟
   SFFLinux联盟
   for (i = 0; i < dataItemJsonNodes.length; i++) { SFFLinux联盟
   var dataItemJsonNode = dataItemJsonNodes[i]; SFFLinux联盟
   this._dataItems[dataItemJsonNode.id] = eval(dataItemJsonNode.content); SFFLinux联盟
   } SFFLinux联盟
   SFFLinux联盟
   //... SFFLinux联盟
  } SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    在官方文档的示例中,字符串“more data”会被序列化为“"more data"”(请注意多出的双引号),这样从eval方法中得到的结果就是“more data”,这正是我们注册的内容。这个再正常不多了,不是吗?猜猜看如果我们将一个序列化的对象注册到客户端时会发生什么事情呢?我为此写了一个示例: SFFLinux联盟
   SFFLinux联盟
  注册一个对象 SFFLinux联盟
  // the definition of Person class SFFLinux联盟
  public class Person SFFLinux联盟
  { SFFLinux联盟
   public string Name; SFFLinux联盟
  } SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
  // the code to register a Person object SFFLinux联盟
  Person person = new Person(); SFFLinux联盟
  person.Name = "Jeffz"; SFFLinux联盟
   SFFLinux联盟
  JavaScriptSerializer serializer = new JavaScriptSerializer(); SFFLinux联盟
  ScriptManager.GetCurrent(this.Page).RegisterDataItem( SFFLinux联盟
   this.UpdatePanel1, serializer.Serialize(person), true); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    当我们进行异步更新时就会抛出异常。似乎这是因为服务器端注册的表示Person对象的JSON字符串“{"Name":"Jeffz"}”无法被直接传递进入eval方法。具体的原因关乎语法方面的问题,可以在ECMAScript Specification中找到解释,因此我在这里就不多作解释了。那么,请注意我下面的代码: SFFLinux联盟
   SFFLinux联盟
  为JSON字符串添加括号 SFFLinux联盟
  ScriptManager.GetCurrent(this.Page).RegisterDataItem( SFFLinux联盟
   this.UpdatePanel1, "(" + serializer.Serialize(person) + ")", true); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    现在,我们的代码就能正常工作了,于是我们就可以在客户端将Person对象取出: SFFLinux联盟
   SFFLinux联盟
  在客户段取出Person对象 SFFLinux联盟
  Sys.WebForms.PageRequestManager.getInstance().add_pageLoading( SFFLinux联盟
   function(sender, e) SFFLinux联盟
   { SFFLinux联盟
   var person = e.get_dataItems()["<%= this.UpdatePanel1.ClientID %>"]; SFFLinux联盟
   alert(person.Name); // "Jeffz" SFFLinux联盟
   }); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    这样看来,这个问题也就可以使用这个方法来解决了。不过为什么ASP.NET AJAX会使用eval方法,而不是定义在Microsoft AJAX Library中的deserialize方法来反序列化一个对象呢?我们可以发现,在deserialize方法中,一个表达式被传递给eval方法之前会被自动加上括号: SFFLinux联盟
   SFFLinux联盟
  desrialize方法 SFFLinux联盟
  Sys.Serialization.JavaScriptSerializer.deserialize = function (data) SFFLinux联盟
  { SFFLinux联盟
   try SFFLinux联盟
   { SFFLinux联盟
   var exp = data.replace(...); SFFLinux联盟
   return eval('(' + exp + ')'); SFFLinux联盟
   } SFFLinux联盟
   catch (e) SFFLinux联盟
   { SFFLinux联盟
   throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson); SFFLinux联盟
   } SFFLinux联盟
  } SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    我猜想,会不会是因为编写部分刷新相关代码的开发人员并不完全了解Microsoft AJAX Library中的功能呢?不过可能性最大的原因则是这些代码没有被完整地Review和测试过。事实上这并不是ASP.NET AJAX最终版本中唯一的bug,其他的还包括那个著名的“跨域名frame的拒绝访问错误”和StringBuilder的Bug。 SFFLinux联盟
   SFFLinux联盟
    嗯,我们问题也看够了,就把目光移向别处吧。尽管逻辑上一个Data Item应该是一个包含信息的对象,但是请注意我们是使用eval方法来“反序列化”一个JSON字符串的。这意味着我们事实上可以将任意的合法表达式发送到客户端,然后它就会被正确执行。请看下面的示例: SFFLinux联盟
   SFFLinux联盟
  服务器端代码 SFFLinux联盟
  ScriptManager.GetCurrent(this.Page).RegisterDataItem( SFFLinux联盟
   this.UpdatePanel1, "var __f = function(){alert('Hello World!');}; __f;", true); SFFLinux联盟
   SFFLinux联盟
  客户端代码 SFFLinux联盟
  Sys.WebForms.PageRequestManager.getInstance().add_pageLoading( SFFLinux联盟
   function(sender, e) SFFLinux联盟
   { SFFLinux联盟
   e.get_dataItems()["<%= this.UpdatePanel1.ClientID %>"](); SFFLinux联盟
   }); SFFLinux联盟
   SFFLinux联盟
   SFFLinux联盟
    我在上面代码中将一个函数注册为一个Data Item并且在客户端将其执行了。如果您深入了解UpdatePanel局部刷新的过程,您会注意到您在服务器端注册的JavaScript代码只有在页面更新结束后才会生效,也就是说,我们无法在pageLoading事件被触发时执行这些代码。我会在之后的文章中针对这样的设计以及如何使用work arounds来解决这个问题进行详细的探讨。这些work arounds就是基于Data Item注册的使用方式的,因为表示Data Item的“JSON字符串”在pageLoading触发之前就被解释执行。 Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
无相关信息