根据Visual Studio的例子:客户端回调实现 (C#) 示例 ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_aspnetcon/html/2c688b1a-93a4-4dad-b82b-63974bdbb13e.htm
HTML代码
<% ... @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " ClientCallbackSample.aspx.cs " Inherits = " ClientCallbackSample " %> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" > < html xmlns ="http://www.w3.org/1999/xhtml" > < head id ="Head1" runat ="server" > < title > 演示在 ASP.NET 网页中不经过回发而实现客户端回调 </ title > < script type ="text/javascript" > ... function LookUpStock() ... { var lb = window.document.getElementById( " ListBox1 " ); if (lb.selectedIndex != - 1 ) ... { var product = lb.options[lb.selectedIndex].text; CallServer(product, "" ); } else ... { alert( " 请从上面列表中选择一项产品! " ); } } function ReceiveServerData(rValue) ... { Results.innerText = rValue; } </ script > </ head > < body > < form id ="form1" runat ="server" > < div > < asp:ListBox ID ="ListBox1" Runat ="server" ></ asp:ListBox > < br /> < br /> < button onclick ="LookUpStock()" > Look Up Stock </ button > < br /> < br /> Items in stock: < span id ="Results" ></ span > < br /> < br /> < br /> </ div > </ form > </ body > </ html >
后台CS
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class ClientCallbackSample : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler ... { protected System.Collections.Specialized.ListDictionary catalog; protected void Page_Load( object sender, EventArgs e) ... { String cbReference = Page.ClientScript.GetCallbackEventReference( this , " arg " , " ReceiveServerData " , " context " ); String callbackScript; callbackScript = " function CallServer(arg, context) " + " { " + cbReference + " } ; " ; Page.ClientScript.RegisterClientScriptBlock( this .GetType(), " CallServer " , callbackScript, true ); // if (!IsPostBack) // { // Label label = new Label(); // label.Text = "中华人民共和国!"; // form1.Controls.Add(label); // } catalog = new System.Collections.Specialized.ListDictionary(); catalog.Add( " monitor " , 12 ); catalog.Add( " laptop " , 10 ); catalog.Add( " keyboard " , 23 ); catalog.Add( " mouse " , 17 ); ListBox1.DataSource = catalog; ListBox1.DataTextField = " key " ; ListBox1.DataBind(); } private string _returnValue; public void RaiseCallbackEvent(String eventArgument) ... { String returnValue; if (catalog[eventArgument] == null ) ... { returnValue = " -1 " ; } else ... { returnValue = catalog[eventArgument].ToString(); } _returnValue = returnValue; } ICallbackEventHandler 成员 #region ICallbackEventHandler 成员 public string GetCallbackResult() ... { return _returnValue; } #endregion }
测试后存在以下问题
HTML的LookUpStock函数中的var lb=document.form1[0].ListBox1出错,改为var lb=window.document.getElementById("ListBox1"]才通过,原因常未弄清楚。 按帮助中源代码调试,在不选择ListBox项就点击Look Up Stock按钮时的JS错误是因为默认情况下,ListBox的selectedIndex为-1,现加入一个判断,当用户还未选择 时点击,给一个提示信息 例子中后台CS代码实现了ICallBackEnevtHandler接口,但是存在两个问题是:该接口必须实现的两个方法第一是public void RaiseCallbackEvent(String eventArgument), 注意是void;第二是public string GetCallbackResult()而例子很奇怪,RaiseCallbackEvent本是void的,他它却是返回string,并且例子中也没有实现GetCallbackResult方法, 难道是Microsoft搞错了...., 导致在调试时报错,解决办法,将RaiseCallbackEvent方法改为void类型,并加入了一个全局的成员变量来将客户端传递的字符串eventArgument纪录, 并由GetCallBackResult返回 。 ClientScript.GetCallbackEventReference方法的context参数还未明白具体的作用是什么。
在完成以上工作以后,我发现每次点击Look Up stock按钮时,程序仍然都会从PageLoad开始执行,我在想这样和Asp.net正常的回发有什么区别呢?难道就只是欺骗了眼睛,页面看起只是局部刷新而已?于是我 写了一小段代码来测试,在页面第一次加载时(也就是!IsPostback)动态创建了一个Label,给Label的Text指定一个值,在页面回发时不重新创建这个Label,在正常情况下,当产生PostBack时,这个Label肯定是 会不见的,但在这个例子中,动态创建的Label在我点击一次,甚至N次按钮之后,依然好好的显示在浏览器上,得出的结论应该是通种方式实现客户端回调,没有丢失客户端状态,所以这种方式的好处就是 帮助中第一段落: 在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作。此时将重新创建页及其控件,并在服务器上运行页代码,且新版本 的页被呈现到浏览器。但是,在有些情况下,需要从客户端运行服务器代码,而不执行回发。如果页中的客户端脚本维护一些状态信息(例如,局部变量值),那么发送页和获取页的新副本就会损坏该状态。此外, 页回发会导致处理开销,这会降低性能,且会让用户不得不等待处理并重新创建页。若要避免丢失客户端状态并且不导致服务器往返的处理开销,可以对 ASP.NET 网页编码,使其能执行客户端回调。在客户端回调中, 客户端脚本函数会向 ASP.NET 网页发送一个请求。该网页运行其正常生命周期的修改版本 — 初始化页并创建其控件和其他成员,然后调用特别标记的方法。该方法执行代码中编写的处理过程,然后向浏览器返回可 由另一客户端脚本函数读取的值。在此过程中,该页一直驻留在浏览器中。