实例:页面无刷新加载外部文件,并显示内容。
新建一个页面,页面代码如下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
#div_content
{
width:80%;
height:auto;
margin:10px auto 10px auto;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<dl>
<dd>
<input id="Button1" type="button" value="点击这里,无刷新显示文章内容"/>
</dd>
</dl>
<div id="div_content">
</div>
</div>
</form>
</body>
</html>
打开页面对应的CS文件,显示实现ICallbackEventHandler接口(代码如下):
public partial class JsCallTest : System.Web.UI.Page,ICallbackEventHandler
{
private string result;
#region ICallbackEventHandler 成员
string ICallbackEventHandler.GetCallbackResult()
{
return result;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
result =LoadHTML("Article/20110509154200.htm");
}
#endregion
}
给该类添加几个简单的加载处理外部文件的方法
/// <summary>
/// 加载外部文件,获取内容
/// </summary>
/// <param name="Path"></param>
/// <returns></returns>
public string LoadHTML(string Path)
{
System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("gb2312");
StreamReader sr = new StreamReader(Server.MapPath("~/") + Path, encoding);
string str = "";
while (sr.Peek() != -1)
{
char[] buffer = new char[4096];
int bufferFillSize = sr.ReadBlock(buffer, 0, 4096);
str = str + new string(buffer);
}
sr.Close();
string strResult = findUsedFromHtml(str, Path);
return strResult;
}
/// <summary>
/// 获取html的内容部分
/// </summary>
/// <param name="strHtml"></param>
/// <returns></returns>
private string findUsedFromHtml(string strHtml, string strFileName)
{
string strBody;
int bodyStart = strHtml.IndexOf("<body");
int bodyEnd = strHtml.IndexOf("</body>");
//html开始到<body>前部分
ViewState["strTop"] = strHtml.Substring(0, bodyStart);
// Body部分
strBody = strHtml.Substring(bodyStart, bodyEnd - bodyStart + 7);
// Body部分后到html结尾部分
ViewState["strBottom"] = strHtml.Substring(bodyEnd, strHtml.Length - bodyEnd);
//替换图片地址
string fullName = strFileName.Substring(strFileName.LastIndexOf("\\") + 1);
string strOld = fullName.Replace("htm", "files");
string strTemp = strFileName.Replace("htm", "files"); ;
string strNew = ResolveUrl("~/" + strTemp);
strBody = strBody.Replace(strOld, strNew);
return strBody;
}
给前台页面添加一个处理函数:
<script language="javascript" type="text/javascript">
function CallService(content) {
content.innerHTML = "加载中......";
<%= ClientScript.GetCallbackEventReference(this,"","ReviceService","content")%>
function ReviceService(result,content){
content.innerHTML=result;
}
}
</script>
给前台页面的input 添加调用:onclick="CallService(div_content)"
1.为HTML客户端控件增加回发功能
一般页面中的按钮并不都是type=submit类型的,大部分是type=button类型的按钮,把type=submit修改成type=button,修改后的代码如下:
output.Write("<INPUT TYPE=button name=" + this.UniqueID + " Value='[使用提交按钮]' />");
由于此代码段中的按钮的type属性由sumbit改成了一般按钮类型button,则此按钮输出后将不再具有回发到服务端的功能。
为了使一般按钮也具有回发的功能,ASP.NET提供了Page.ClientScript.GetPostBackEventReference方法。
ClientScript类型为ClientScriptManager,该类主要功能是在Web应用程序中定义用于管理客户端脚本的方法。GetPostBackEvent Reference方法体结构如下:
GetCallbackEventReference(String, String, String, String, String, Boolean)
此方法功能是获取一个对客户端函数的引用;调用该方法时,将启动一个对服务器事件的客户端回调。
此重载方法的客户端函数包含指定的目标、参数、客户端脚本、上下文、错误处理程序和布尔值。
在期望不执行回发而从客户端运行服务器代码的情况下,可以使用ClientScriptManager类来调用客户端回调。这称为对服务器执行带外回调。
在客户端回调中,客户端脚本函数向ASP.NET网页发送异步请求。网页修改其正常生命周期来处理回调
使用GetCallbackEventReference方法对上面代码增加回调客户端功能,修正后的代码如下:
output.Write("<INPUT type=button name=\"{0}\"
value='[使用Page.ClientScript对象方法]' onclick=\"{1}\">",
this.UniqueID, Page.ClientScript.GetPostBackEvent Reference(this, ""));
Page.ClientScript.GetPostBackEventReference方法参数介绍:
第一个参数传递当前控件引用,在实际应用中可以传递任意控件引用,包括子控件;
第二个参数为可选的命令参数,这里设置为null,一般同时处理多个按钮时可以设置该参数为不同的命令名称。
转入正题,在代码中增加按钮的onclick单击事件,当单击按钮时会调用GetPostBackEvent Reference方法返回的一串客户端脚本,并且在页面中生成一个客户端方法和两个type=hidden的隐藏域控件。
下面是以上代码呈现到客户端的HTML代码:
<INPUT type=button name="PostBackFromClientControl1"value='
[使用Page. ClientScript对象方法]'onclick="__
doPostBack('PostBackFromClientControl1','')">
<div>
<input type="hidden" name="__EVENTTARGET"
id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT"
id="__EVENTARGUMENT" value="" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
从上面最终输出的HTML源代码可以看到,Button控件的单击事件会执行一个名为_doPostBack的方法,并且此方法也是自动生成在页面中的。在_doPostBack方法中把事件目标对象eventTarget(调用GetPostBackEventReference方法时传递的第一个参数,为当前控件)赋值给当前Form对象,把事件参数对象eventArgument(调用GetPostBackEventReference方法时传递的第二个参数),最后调用Form对象的提交方法,提交窗体,到这里就实现了我们想要的回发功能。
还要注意到以下两句自动生成的代码:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
这是两个隐藏域类型控件,主要用来存储事件目标对象和事件参数对象的值。还有,在以上的script标记之间,有个嵌套的//<![CDATA[ //]]> 子句,该句与纯控件开发技术无关。该句的功能是通知HTML读取器下面这段不是HTML的内容,需要按附加的转义字符分开保存,以防代码解析出错。
2.为服务端控件生成回发脚本
Page.ClientScript.GetPostBackEventReference方法还可以为服务端控件生成自己的回发脚本,可以从客户端回发。
ASP.NET标准的Button服务端控件最终生成的HTML标记无非也是生成一个type=submit类型的控件。
对于服务端控件也可以设置客户端回发功能。比如在使用Button控件时把UseSubmitBehavior属性设置为false,则禁用按钮的自动提交功能,就可以使用GetPostBackEventReference方法返回Button控件的客户端回发事件脚本,代码如下所示:
string strPostBackCode = this.Page.ClientScript.GetPostBackEventReference(button1,"edit");
然后把Button的客户事件与生成的回发事件脚本进行关联:
this.button1.Attributes["onclick"] = strPostBackCode;
其他服务端控件也是这样设置的。
GetCallbackEventReference方法介绍
Page.ClientScript对象还有个非常重要的方法GetCallbackEventReference。
使用GetCallbackEventReference方法获取一个对客户端函数的引用,当调用该函数时,它将启动一个对服务器端事件的客户端回调,可以支持设置客户端回调方法名称等
服务器端控件的局部刷新,CallBack2007-08-13 8:02发现了.net2.0原来有套CallBack机制,可以轻松实现服务器控件类似AJAX的效果(实现局部刷新),不过真的是服务器端控件用AJAX的话,效果确乎是没ASP.NET AJAX 好
Callback与asp.net ajax的UpdatePanel控件内在实现机制都是Ajax
但采用UpdatePanel控件的页面仍然采用Postback方式与服务器交互,会更新ViewState
Callback采用xmlhttp(GET方式)或是iframe,这个过程根本没有涉及到页面的 ViewState (还是没有解决服务器端控件的ViewState问题,而且只支持asp.net2.0,还有很多缺陷,个人不推荐使用)
http://www.cnblogs.com/teddyma/archive/2005/11/28/286196.html 深度解析Asp.Net2.0中的Callback机制
http://www.cnblogs.com/jailu/archive/2007/06/26/796045.html 体验ASP.NET2.0客户端回调功能(CallBack)
http://msdn2.microsoft.com/zh-cn/library/system.web.ui.icallbackeventhandler(VS.80).aspx MSDN
●一个完整的回调包含以下几个过程:
(1)客户端发出callback请求;
(2)服务器端接收客户端callback请求;GetCallbackEventReference接受
(3)服务器端处理请求并回发请求给客户端;RaiseCallbackEvent处理,GetCallbackResult返回
(4)客户端接收服务器的返回结果并更新HTML。
●string Page.ClientScript.GetCallbackEventReference( //获取一个对客户端函数的引用
string target, //处理客户端callback的服务器控件的名称(实现ICallbackEventHandler接口)
string argument, //从JS传递给服务器端RaiseCallbackEvent方法的1个参数
string clientCallback,//接收服务器处理结果的JS函数名。
string context,//原封不动的传给指定的返回数据处理的JS函数
string clientErrorCallback,//服务器端事件处理程序出现错误时接收结果的JS函数
bool useAsync //true同步;false异步
)
●void Page.ClientScript.RegisterClientScriptBlock ( //向Page对象注册客户端脚本
Type type, //要注册的客户端脚本的类型
string key, //要注册的客户端脚本的名称
string script, //要注册的客户端脚本内容
bool addScriptTags //指示是否添加脚本标记的布尔值
)
1。要使用Callback首先要继承ICallbackEventHandler接口:
public partial class Callback : Page, ICallbackEventHandler
或:
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
2。实现ICallbackEventHandler接口的两个方法
string GetCallbackResult() //返回一个string类型(只能是string类型)的数据给客户端脚本
{
//////
}
void RaiseCallbackEvent(string eventArgument) //含一个string类型的传入参数,可用于接收客户端脚本的参数
{
///////
return "";
}
3。处理回调页面的Page类还需负责客户端回调脚本的管理:指明哪个JS函数发送callback请求、哪个JS函数接收数据。
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
string strRefrence = Page.ClientScript.GetCallbackEventReference(this, "arg", "AAA", "context");
// 这里AAA是callback成功之后,客户端接收结果的JS方法,可以包含两个参数。
//this表示执行callback的的服务端控件是当前这个Page,当前的Page必须实现ICallbackEventHandler接口
//arg是传给RaiseCallbackEvent的参数eventArgument的值,可以用自定义格式的字符串。
//context参数会被原封不动的传给指定的返回数据处理的JS函数
string strCallBack = "function BBB(arg, context) {" + strRefrence + "};";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "BBB", strCallBack, true); ////注册JS函数BBB,BBB触发GetCallbackEventReference
}
}
这样写更好理解点
<script language="javascript" type="text/javascript">
function BBB(arg, context)
{<%= ClientScript.GetCallbackEventReference(this, "arg", "AAA", "context")%>;}
</script>
●前者把JS函数BBB写在了服务器端然后用RegisterClientScriptBlock注册,客户端调用BBB,BB再调用了GetCallbackEventReference
第2种,BBB直接写在客户端。
4。客户端代码:客户端脚本则比较简单了,只需要实现接收callback结果的JS方法(这里是AAA)就OK了
function AAA(valueRES, context) //valueRES是服务器端处理后的结果
{
document.getElementById(elementId1).innerHTML = valueRES;
document.getElementById(elementId2).innerHTML = context;
}
例子:用callback获取服务器端的时间(12和24小时制)
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, ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string strRefrence = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveDataFromServer", "context");
string strCallBack = "function CallBackToTheServer(arg, context) {" + strRefrence + "};";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CallBackToTheServer", strCallBack, true); //注册JS函数CallBackToTheServer
}
}
private string strTimeFormat;
public string GetCallbackResult()
{
if (strTimeFormat != "" && strTimeFormat == "12")
{return DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss(12小时制)");}
else
{return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss(24小时制)");}
}
public void RaiseCallbackEvent(string eventArgument)
{
strTimeFormat = eventArgument;
}
}
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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>CallBack</title>
<script language="javascript" type="text/javascript">
function ReceiveDataFromServer(valueReturnFromServer,context)
{
document.getElementById("ServerTime").innerHTML = valueReturnFromServer;
document.getElementById("PIG").innerHTML = context;
}
function GetServerTime(format)
{CallBackToTheServer(format, "你是猪");} //调用触发GetCallbackEventReference的CallBackToTheServer函数(写在服务器端的JS函数)
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnShow12" runat="server" Text="获取服务器时间(12小时制)" OnClientClick="javascript:GetServerTime(12);return false;" /><br />
<asp:Button ID="btnShow24" runat="server" Text="获取服务器时间(24小时制)" OnClientClick="javascript:GetServerTime(24);return false;" /><br />
<br />
<span id="ServerTime"><%= DateTime.Now.ToString("yyyy-MM-dd HHHH:mm:ss") %></span>不点击则为默认显示
<span id="PIG"></span>
</div>
</form>
</body>
</html>