浅谈实例Page Method到静态Page Method的移植2011-08-28最近被问及Page Method的问题比较多,主要还是如何从Atlas CTP中的非静态Page Method转向Beta或RC中的静态Page Method时所遇到的问题。现在我来谈一下在这方面的一些看法,也希望大家能和我一起探讨一下。在当时,只要在Code Behind的Page类中添加一个实例方法,并且使用WebMethodAttribute进行标记即能使用,例如:[WebMethod]
public string GetString(string split)
{
  return this.TextBox1.Text + split + this.TextBox2.Text;
}
可以看到上面的方法能够通过this引用访问到页面中的控件,然后取它们的值。如果要在客户端调用的话,只要在页面中编写JavaScript代码即可,如下:
function successCallback(result)
{
  ...
}
PageMethods.GetString("|", successCallback);
然而在Beta和RC的ASP.NET AJAX中则移除了实例方法的Page Method,于是之前的用法已经完全不兼容了,而且不是那么轻易地就可以进行移植。其实方法总是有的,而且似乎也不是非常的费事,不过在这之前,我们还是来思考一下实例的Page Method与静态的Page Method相关的问题吧。静态Page Method与实例Page Method的实现方式有什么区别呢?静态的Page Method的实现原理其实和客户端调用Web Service如出一辙,几乎没有任何的区别。而实例Page Method在调用时和UpdatePanel有些接近——至少在一开始,因为它们为了获得整个控件树的信息,必须将页面上的所有内容,例如所有输入控件的值,连同ASP.NET存放在客户端的ViewState等信息一并发送到服务器端。喔,这不就相当于一个完整的PostBack吗?它与静态Page Method相比,最大的劣势也就在这里:性能。实例Page Method在每次调用时都必须传输更多的数据,在构造一棵完整的控件树,换来的是访问控件树的能力——再明确点说,换来的“只是”访问控件树的能力。其它功能的可以说几乎完全没有,例如对于控件的修改无法输出到客户端。下面我们也必须考虑一下,静态Page Method与实例Page Method相比,究竟有哪些限制呢?如果这种限制对于功能影响太大,那么只能牺牲一些性能了。我们作最坏打算,也不过是相当于作了一次“完整”的刷新么。估计最大的限制就是无法访问页面的“控件树”了,例如下拉框的选项。不过就是因为这一点,我们就必须重建页面的控件树吗?如果是客户端控件的属性,我们可以直接在客户端得它的属性之后,将它作为静态Page Method的参数。如果是其它的值,我们在生成页面时是如何获得的,那么就在静态Page Method中再获得一次吧。其实在我遇到的很多问题中,发现几乎所有的情况都是可以使用“客户端获得数据,再作为服务器端方法的参数”这种做法。例如之前的例子就可以转换成下面的做法。[ScriptMethod]
public string GetString(string split, string text1, string text2)
{
  return text1 + split + text2;
}
function successCallback(result)
{
  ...
}
var text1 = $get("<%= this.TextBox1.ClientID %>").value;
var text2 = $get("<%= this.TextBox2.ClientID %>").value;
PageMethods.GetString("|", text1, text2, successCallback);