ASP.NET 网页中不经过回发而实现客户端回调

来源:互联网 发布:淘宝客服的工作怎么找 编辑:程序博客网 时间:2024/04/29 09:48
在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作。此时将重新创建页及其控件,并在服务器上运行页代码,且新版本的页被呈现到浏览器。但是,在有些情况下,需要从客户端运行服务器代码,而不执行回发。如果页中的客户端脚本维护一些状态信息(例如,局部变量值),那么发送页和获取页的新副本就会损坏该状态。此外,页回发会导致处理开销,这会降低性能,且会让用户不得不等待处理并重新创建页。

若要避免丢失客户端状态并且不导致服务器往返的处理开销,可以对 ASP.NET 网页编码,使其能执行客户端回调。在客户端回调中,客户端脚本函数会向 ASP.NET 网页发送一个请求。该网页运行其正常生命周期的修改版本 — 初始化页并创建其控件和其他成员,然后调用特别标记的方法。该方法执行代码中编写的处理过程,然后向浏览器返回可由另一客户端脚本函数读取的值。在此过程中,该页一直驻留在浏览器中。

有几个 Web 服务器控件使用客户端回调。例如,TreeView 控件使用客户端回调实现其即需填充功能。有关更多信息,请参见 TreeView Web 服务器控件概述。

客户端回调组件
创建实现客户端回调的 ASP.NET 页与创建任何 ASP.NET 页类似,但也有如下这些区别。页的服务器代码必须:

实现 ICallbackEventHandler 接口。可以向任何 ASP.NET 网页添加此接口声明。

包括一个实现 RaiseCallbackEvent 接口的方法。此方法将被调用以执行从服务器发出的回调。

此外,该页还必须包含执行以下操作的三个客户端脚本函数:

一个函数调用帮助器方法,该方法执行对服务器的实际请求。在此函数中,可以首先执行自定义逻辑以准备事件参数,然后可以将一个字符串作为参数发送到服务器端回调事件处理程序。

另一个函数由处理回调事件的服务器代码的结果调用并接收该结果,同时接受表示该结果的字符串。该函数称为客户端回调函数。

第三个函数是执行对服务器的实际请求的 Helper 函数,当在服务器代码中使用 GetCallbackEventReference 方法生成对此函数的引用时,由 ASP.NET 自动生成该函数。

客户端回调及回发都是对起始页的请求,因此在 Web 服务器日志中将客户端回调及回发记录为页请求。

在服务器代码中实现合适的接口
若要从客户端成功运行服务器代码而不执行回发,则必须在服务器代码中实现适当的接口。

声明 ICallbackEventHandler 接口
可以将 ICallbackEventHandler 接口作为页的类声明的一部分进行声明。如果创建代码隐藏页,则可以通过使用如下语法声明该接口。

Visual Basic
Partial Class CallBack_DB_aspx
    Inherits System.Web.UI.Page
    Implements System.Web.UI.ICallbackEventHandler
C#
public partial class CallBack_DB_aspx :
    System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
如果正在处理单文件页或用户控件,则可以通过在页中使用 @ Implements 指令来添加声明,如下面的代码示例所示:

Visual Basic
<%@ Page Language="VB" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
C#
<%@ Page Language="C#" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
注意
接口名区分大小写。
 

创建服务器回调方法
在服务器代码中,必须创建一个实现 RaiseCallbackEvent 方法的方法和一个实现 GetCallbackResult 方法的方法。RaiseCallbackEvent 方法接受单个字符串参数,而不是通常用于事件处理程序的常见的两个参数。该方法的部分内容可能与下面的代码示例类似。

Visual Basic
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _
    Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
    Return eventArgument & " new value"
End Sub
C#
public void RaiseCallbackEvent(String eventArgument)
{
    return eventArgument + " new value";
}
GetCallbackResult 不接受参数并返回一个字符串。该方法的部分内容可能与下面的代码示例类似:

Visual Basic
Public Function GetCallbackResult() As String Implements _
    System.Web.UI.ICallbackEventHandler.GetCallbackResult
    Return aStringValue
End Function
C#
public string GetCallbackResult()
{
    return aStringValue;
}
创建客户端脚本函数
必须向页中添加客户端脚本函数以执行两个功能:向服务器页发送回调和接收结果。这两个客户端脚本函数都是用 ECMAScript (JavaScript) 编写。

发送回调
发送回调的函数在服务器代码中生成。实际回调由任何页都可使用的、实现 ICallbackEventHandler 接口的库函数执行。通过调用页的 GetCallbackEventReference 方法可以获取对库函数的引用,该方法可通过页 ClientScript 属性进行访问。然后动态生成一个客户端函数,该函数包含对来自 GetCallbackEventReference 方法的返回值的调用。向该方法传递以下内容:对页的一个引用(在 C# 中为 this,在 Visual Basic 中为 Me)、传递数据时所依据的参数名称、将接收回调数据的客户端脚本函数的名称,以及传递所需的任何上下文的参数。

生成函数之后,通过调用 RegisterClientScriptBlock 方法将其插入到页中。

下面的代码示例演示如何动态创建一个名为 CallServer 的函数,该函数又调用回调。

Visual Basic
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
    Dim cm As ClientScriptManager = Page.ClientScript
    Dim cbReference As String
    cbReference = cm.GetCallbackEventReference(Me, "arg", _
        "ReceiveServerData", "")
    Dim callbackScript As String = ""
    callbackScript &= "function CallServer(arg, context)" & _
        "{" & cbReference & "; }"
    cm.RegisterClientScriptBlock(Me.GetType(), _
        "CallServer", callbackScript, True)End Sub
C#
void Page_Load(object sender, EventArgs e)
{
    ClientScriptManager cm = Page.ClientScript;
    String cbReference = cm.GetCallbackEventReference(this, "arg",
        "ReceiveServerData", "");
    String callbackScript = "function CallServer(arg, context) {" +
        cbReference + "; }";
    cm.RegisterClientScriptBlock(this.GetType(),
        "CallServer", callbackScript, true);
}
由正在生成的函数接受的参数名称应与传递给 GetCallbackEventReference 方法的值的名称相匹配。

下面的代码示例演示一些可用于调用回调并处理其返回值的标记:

Visual Basic
<input type="button" value="Callback"
    onclick="CallServer(1, alert('Callback'))"/>
<br />
<span id="Message"></span>
C#
<input type="button" value="Callback"
    onclick="CallServer(1, alert('Callback'))"/>
<br />
<span id="Message"></span>
接收回调
可以编写在页中静态接收回调的客户端函数。该函数的名称必须与在 GetCallbackEventReference 方法调用中传递的名称相匹配。接收函数接受两个字符串值:一个用于返回值,另一个(可选)用于从服务器传回的上下文值。

该函数可能与下面的代码示例类似:

<script type="text/javascript">
function ReceiveServerData(arg, context)
{
    Message.innerText = 'Processed callback.';
}
</script>