技术开发 频道

UpdatePanel的妙用:Incremental Content

    现在,我们的代码就能正常工作了,于是我们就可以在客户端将Person对象取出:

    在客户段取出Person对象
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(
function(sender, e)
{
var person = e.get_dataItems()["<%= this.UpdatePanel1.ClientID %>"];
alert(person.Name); // "Jeffz"
});
    这样看来,这个问题也就可以使用这个方法来解决了。不过为什么ASP.NET AJAX会使用eval方法,而不是定义在Microsoft AJAX Library中的deserialize方法来反序列化一个对象呢?我们可以发现,在deserialize方法中,一个表达式被传递给eval方法之前会被自动加上括号:

    desrialize方法
Sys.Serialization.JavaScriptSerializer.deserialize = function (data)
{
try
{
var exp = data.replace(...);
return eval('(' + exp + ')');
}
catch (e)
{
throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson);
}
}
    我猜想,会不会是因为编写部分刷新相关代码的开发人员并不完全了解Microsoft AJAX Library中的功能呢?不过可能性最大的原因则是这些代码没有被完整地Review和测试过。事实上这并不是ASP.NET AJAX最终版本中唯一的bug,其他的还包括那个著名的“跨域名frame的拒绝访问错误”和StringBuilder的Bug。

    嗯,我们问题也看够了,就把目光移向别处吧。尽管逻辑上一个Data Item应该是一个包含信息的对象,但是请注意我们是使用eval方法来“反序列化”一个JSON字符串的。这意味着我们事实上可以将任意的合法表达式发送到客户端,然后它就会被正确执行。请看下面的示例:

    服务器端代码
ScriptManager.GetCurrent(this.Page).RegisterDataItem(
this.UpdatePanel1, "var __f = function(){alert('Hello World!');}; __f;", true);

    客户端代码
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(
function(sender, e)
{
e.get_dataItems()["<%= this.UpdatePanel1.ClientID %>"]();
});
    我在上面代码中将一个函数注册为一个Data Item并且在客户端将其执行了。如果您深入了解UpdatePanel局部刷新的过程,您会注意到您在服务器端注册的JavaScript代码只有在页面更新结束后才会生效,也就是说,我们无法在pageLoading事件被触发时执行这些代码。我会在之后的文章中针对这样的设计以及如何使用work arounds来解决这个问题进行详细的探讨。这些work arounds就是基于Data Item注册的使用方式的,因为表示Data Item的“JSON字符串”在pageLoading触发之前就被解释执行。
0
相关文章