ASP.NET中的GetCallbackEventReference

本文详细介绍ASP.NET中的Callback机制,一种实现在不完全刷新页面的情况下更新部分内容的技术。文章讲解了如何利用ICallbackEventHandler接口和GetCallbackEventReference函数实现客户端与服务器端的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GetCallbackEventReference函数在 .NET Framework 2.0 版中是新增的。

MSDN解释:获取一个对客户端函数的引用;调用该函数时,将启动一个对服务器端事件的客户端回调。此重载方法的客户端函数包含指定的控件、参数、客户端脚本和上下文。
函数原型:
public string GetCallbackEventReference (
Control control,
string argument,
string clientCallback,
string context
)


第一个参数指定了服务器端将要处理回调的目标对象,即处理客户端回调的服务器端控件。该控件必须实现 ICallbackEventHandler 接口并提供 RaiseCallbackEvent 方法。
    如果传入的是this,则表示页面本身。也可以传入任何实现了ICallbackEventHandler的页面控件(page control)的引用。
    在任何情况下,客户端的提交动作(submit action)会提交至和标准回传(postback)机制相同的ASPX页面。
第二个参数是一个JavaScript常量表达式,表示页面传给服务器的输入数据。如将一个下拉列表当前选中元素的值传入"document.getElementById['cboEmployees'].value":。
第三个参数是一个用户定义在<script>块中的JavaScript回调(callback)函数名。回调(callback)执行后,此函数最终负责页面的更新。
最后两个可选参数可用来指定错误处理函数(error handler)和上下文对象(context object)。

GetCallbackEventReference函数将产生如下的脚本调用:
WebForm_DoCallback(pageID, input, UpdateEmployeeViewHandler, null, null);
此函数的代码会自动下载到客户端并通过<script>标签添加到页面响应(page's response)中。WebForm_DoCallback 使用XmlHttpRequest DOM对象(XmlHttpRequest DOM object)回调(call back)当前页面的URL。
与此同时,它会添加一些额外的隐藏域(hidden field)以便服务器区分更简单的轻量级回调(callback)请求和一般回传(postback)请求。
处理请求时,ASP.NET运行时(runtime)标识出调用的目标对象(传给GetCallbackEventReference的第一个参数),确认它实现了ICallbackEventHandler接口后调用RaiseCallbackEvent方法:
void RaiseCallbackEvent (
string eventArgument
)
eventArgument一般即是通过GetCallbackEventReference指定的页面传递到服务器端的输入数据,即参数2
RaiseCallbackEvent处理完毕,即通过调用
public string GetCallbackResult()
将处理结果返回给调用控件,交由客户端执行GetCallbackEventReference指定的客户端脚本clientCallback,由其完成客户端刷新。

上面说过,脚本回调(script callback)并不适用于所有浏览器,尽管最新的浏览器,包括Internet Explorer 5+, Netscape 6+, and Safari1.2+都能行。
Microsoft在ASP.NET 2.0中加入了两个新的browser bapabilities:SupportsXmlHttp 与SupportsCallback以便开发人员检查方案的可行性。
一条让页面刷新更快的告诫
尽管脚本回调(script callback) 定义在ASP.NET 2.0中,要使其在ASP.NET 1.1里工作也并不很困难。在ASP.NET 2.0中,很多服务器控件(server control)借助脚本回调(script callback)提供了更迅速的页面刷新。
最突出的例子也许是GridView控件(GridView control),作为DataGrid的接班人,选择性地运用脚本回调(script callback)实现分页显示记录。
正如前面所说,脚本回调(script callback)依赖于文档对象模型(DOM)的XmlHttpRequest对象。在Internet Explorer中,此文档对象模型对象(DOM object)通过ActiveX控件(ActiveX control)实现——Microsoft.XmlHttp。
在IE中浏览这样的页面时,你必须适当降低安全设置以允许ActiveX控件(ActiveX control)能被脚本调用。在其他以同样方式实现XmlHttpRequest文档对象模型对象(DOM object)的浏览器中,这是不必要的。
事实上,基于Mozilla的浏览内置支持了HTTP请求功能器,而没用使用ActiveX控件(ActiveX control)——这也是在Internet Explorer 7.0中被寄予厚望的功能。

下面简单例子可作参考:
服务器端


public partial class _Default : System.Web.UI.Page , ICallbackEventHandler
{
    private string callbackResult = string.Empty;
    private string s = string.Empty;
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ClientScriptManager csManager = Page.ClientScript;
            string callbackMethod = csManager.GetCallbackEventReference(this, "document.getElementById('txtNow').value", "JS_OnClickFunc", "this.value");
            txtNow.Attributes.Add("OnClick", callbackMethod);
        }
    }

    ICallbackEventHandler 成员#region ICallbackEventHandler 成员

    public string GetCallbackResult()
    {
        return callbackResult;
    }

    public void RaiseCallbackEvent(string eventArgument)
    {
        callbackResult = eventArgument + System.DateTime.Now.ToString();
    }

    #endregion
}

客户端


<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<html>
<head runat="server">
    <title>无标题页</title>
    <script language="javascript">
    function JS_OnClickFunc(a)
    {
        document.getElementById("txtNow").value = a;
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:TextBox ID="txtNow" runat="server" ></asp:TextBox>
    </div>
    </form>
</body>
</html>

 

现在.NET的Ajax组件确实不少了,微软的ajax extensions用起来很方便,一个UpdatePanel就可以搞定一切。不过,可能有些朋友更愿意自己来写。那么在.NET里,你是否知道ICallbackEventHandler呢?

大家应该都知道ASP.NET页面调用时的几种方式:Postback/Cross-page posting/Server transfer/Callback,如果你还不太了解,你可以看看MSDN:How to: Determine How ASP.NET Web Pages Were Invoked

现在要说的,就是Callback这种调用方式。
简单的说,使用Callback可以得到你平常看到那么Ajax效果,即不刷新整个页面,只更新其中一个部分。

使用Callback,只需要做以下4步:

1、在你的页面中继承System.Web.UI.ICallbackEventHandler接口

public partial class _Default : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    #region ICallbackEventHandler Members
    public string GetCallbackResult()
    {
    }
    public void RaiseCallbackEvent(string eventArgument)
    {
    }
    #endregion
}

如果你没有使用code-behind,那你也可以在aspx页面顶部加入下面的代码:

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

2、在前台写一段自定义的javascript,更新页面

这一段javascript用来更新页面的某个局部,就像你平常操作的一样,写些document.getElementById("xxx").innerHTML="working on your request...."。

    <script type="text/javascript">
    function GetFlag(arg)//这里已经得到服务器端数据据了,服务器端数据就在这个参数arg里。
    {
        document.getElementById("result").innerHTML=arg;//我们不作处理,直接显示在页面上。
    }
    </script>

你可能有些迷糊,就得到了吗?连个什么XMLHttpRequest都没有哩……

3、在Page_Load中再注册一段javascript

string script = Page.ClientScript.GetCallbackEventReference(this, "arg", "GetFlag", "");
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), .......//省略了一大串

上面的GetCallbackEventReference是用来得到客户端函数的引用,发起一个callback到服务器端的,你不必知道详细内容。

你只需要了解:

  • 第一个参数填this,用来handle客户端的callback的,它必须继承ICallbackEventHandler接口并提供RaiseCallbackEvent方法,我们已经在继承了这个接口,上面第一点中的代码也有RaiseCallbackEvent方法,只是还没有具体写内容呢。
  • 第二个参数就是那个 从客户端传到服务器端的参数。如果你想要注册的检查用户是否可用,那么这里的值就是用户输的那个值。
  • 第三个参数是前台的javascript函数名,在第二步中我们写的名字是:GetFlag。当数据好了,这个javascript函数就会用到。
  • 第四个参数一般用不上。

返回值:一个函数的名字,是客户端调用的函数名。这个函数会调用到服务器端了。

4、调用你的函数。

<input type="button" value="check it!" onclick="callServer()" />

上面一定是 onclick="callServer()"吗?呵呵,这要看你了,你在Page.ClientScript.RegisterClientScriptBlock注册的什么javascript函数名字,就是什么名字了。(在第3步的第二行code中)

已经完了。如果你还是一头雾水,没关系,下面看一个实例

我们写一个检测用户是否已经注册的小程序,这在每个用户注册页面上都可以用到。

前台Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" EnableViewState="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>ICallbackEventHandler Demo</title>
    <style type="text/css">
    *{font: 12px "verdana";}
    #user{border:1px solid #080; height:50px;width:500px;padding:20px;}
    input{border:1px solid #508FCC;background:#FFF;}
    .ok{color:#090;}
    .bad{color:#F00}
    #result{display:inline;margin: 0 5px 0;}
    </style>
    <script type="text/javascript">
    function GetFlag(arg)//这里的javascript函数就是服务器查询完成要调用的函数,我们把服务器返回的数据直接显示上ID为result的div中。
    {
        document.getElementById("result").innerHTML=arg;
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div id="user">
            <input type="text" value="99love" maxlength="10" id="userid" />
            <input type="button" value="check it!" onclick="callServer()" /><div id="result">查询用户是否被使用。</div>
        </div>
    </form>
</body>
</html>

上面有一个<input type="button" value="check it!" onclick="callServer()" />,这是我说的第5步的内容,这个函数名字callServer应该和Lage_Load中注册的相对应的。

后台Default.aspx.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 _Default : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
    private string _arg = string.Empty;
    protected void Page_Load(object sender, EventArgs e)
    {
        string script = Page.ClientScript.GetCallbackEventReference(this, "arg", "GetFlag", "");//上面的第3步,取得这个客户端函数名,script的值可能是这样的:WebForm_DoCallback('__Page',arg,GetFlag,/"/",null,false)
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "callServer", "/nfunction callServer(){/ndocument.getElementById(/"result/").innerHTML=/"正在检查 /"+document.getElementById(/"userid/").value+/" 的可用性,请稍候.../";/nvar arg=document.getElementById(/"userid/").value;/n" + script + ";/n}", true);
        //上面这一行有点长了,第二个参数最长,看到function callServer()了吗,这就是和前台对应的那个函数名<input onclick=XXX,请记得,一定要在callServer函数中加入script的值,也就是上一行的上一行(17行)那个值。注意后面的var arg=...,这个arg和17行的arg是对应的。
    }
    #region ICallbackEventHandler Members
    public string GetCallbackResult()
    {
        System.Threading.Thread.Sleep(1000);//让线程睡一会,我们好看效果。这是用来模拟不良网络状况的。
        return _arg;//返回一个string型,这个string在RaiseCallbackEvent函数中是赋过值的,看下面哦。
    }
    public void RaiseCallbackEvent(string eventArgument)
    {
        if (eventArgument.Equals("99love") || eventArgument.Equals("blueidea"))//假设这两个名字不能注册,实际操作中,你要是比对数据库记录的,我们现在简化处理了。
            _arg = string.Format("<span class=/"bad/">很遗憾,{0} 已被使用。</span>", eventArgument);//要么已经注册了
        else
            _arg = string.Format("<span class=/"ok/">恭喜您,{0} 可以注册。</span>", eventArgument);//要么就可以注册
    }
    #endregion
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值