跳出封装剖析ASP.NET脚本回调的原理
来源:互联网 发布:cs架构b2b源码 编辑:程序博客网 时间:2024/05/17 22:58
到处都是Ajax开发框架,其实在ASP.NET 2.0发布的时候内部其实就整合了一些类似的内容,在一些数据控件比如GridView上面就有使用,在05年一月份的MSDN Magazine中的一篇《Custom Script Callback in ASP.NET》(中文版 | English)让我认识到了ASP.NET 里面异步调用的魅力(里面的实现方法仅限于在beta1版本中实现,关于脚本回调部分beta1、beta2以及正式版本之间都有所不同,有兴趣者可以自己参见最近发布的MSDN内容),不过当时也只是玩了一下,后来使用Atlas,也就对它没怎么上心,不过前一段时间一个朋友和我讨论ASP.NET实现ajax时讲到,atlas实现太过于繁琐,而他要实现的只是几个非常小的内容不需要那么麻烦,由于我对除了这些之外的.NET的ajax框架不熟悉,所以自然而然的就想起了内置的脚本回调机制,利用(经过他本人同意的)朋友的项目,我们编写了很多关于这个的代码,在写完之后我突然发现了一个问题,就是代码太乱了。每个页面都是类似的东西,而且只能传递一个字符串参数让我们在除了交互方面对于一些大开销的数据展示只好使用内嵌框架来实现了。前两天到海图买了一本《Ajax 高级语言程序设计》,看了一部分之后突然想搞明白ASP.NET 2.0里面的脚本回调又是如果实现的?其实现在转回来头看,《Custom Script Callback in ASP.NET》一文中很多地方已经讲的很明白了,可以无奈当时的水平,很多东西看的都是云里雾里的,光顾者看效果了先贴一个我认为最简洁的实现效果,然后再进行剖析。
新建一个Default.ASPx的页面,在页面上添加一个CheckBox控件,然后打开Default.ASPx.cs文件,_Default类添加三个继承的接口ICallbackContainer、ICallbackEventHandler和INamingContainer:
[代码1]
#region ICallbackContainer 成员
public string GetCallbackScript(IButtonControl buttonControl, string argument)
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region ICallbackEventHandler 成员
string temp;
public string GetCallbackResult()
{
//throw new Exception("Sample Error");
return temp;
}
public void RaiseCallbackEvent(string eventArgument)
{
temp = "_____" eventArgument " is succeed._____";
}
#endregion
转到Default.ASPx.cs页面的Page_Load方法中加入下面代码:
[代码2]
proected void Page_Load(object sender, EventArgs e)
{
string temp = Page.ClientScript.GetCallbackEventReference(this, "arg", "Callback", "context", "OnError", true);
string script = "function CallServer(arg,context){" temp "}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "abc", script, true);
CheckBox1.Attributes.Add("onclick", "CallServer('I call Server ','context');");
}
在编辑完CS代码之后,打开Default.ASPx文件,在<head>...</head>之间加入下列代码:
[代码3]
<script type="text/javascript">
function OnError(err,context)
{
alert(err);
}
function Callback(arg,context)
{
alert(arg);
}
</script>
这里的CheckBox控件是随便拉上去的,有需要可以随便更改,不过用Button控件的时候可能要注意一下,它默认就会激活OnSubmit事件,所以可能要设置或是直接使用HTML控件就好了。以上的代码算是脚本回调最小化的实现,都是必须的缺一不可。
使用基本回调的控件必须实现三个接口分别是:ICallbackContainer,INamingContainer和ICallbackEventHandler。其实INamingContainer没有需要实现的接口内容,它只是“标识在 Page 对象的控件层次结构内创建新 ID 命名空间的容器控件”(引自MSDN)。至于ICallbackContainer这个接口,在MSDN(中文版本)里面给出的解释比较模糊,相关联的一些文章也都是介绍脚本回调和ICallbackEventHandler接口的,因为我们这里是用页面作为回调的基础,所以没有使用这个接口要实现的方法GetCallbackScript,但是如果是封装自己的Ajax控件那这个方法就十分有用了,这里我们只是用了ICallbackEventHandler实现的方法来处理数据,因为在Page_Load方法中我注册了一个CallServer的方法,然后依附于CheckBox的OnClick事件上触发,这样我们就可以看法一个比较清晰的调用过程了。
后面[代码3]我实现了两个Javascript方法,一个是用来处理调用出错的,另外一个就是用来处理调用成功之后处理返回信息的了。在[代码1]里面有一段抛出异常的代码被我注释掉了,通过这句代码就可以模拟调用OnError方法了。
一直到这里我们都是看到的实现这个调用是怎么样的,说白了这其实算是一种比价高级的拖控件的方式,但是它到底是怎么实现的呢?为什么我没有看到任何有关于XmlHttpRequest的内容呢?(我坚信这是实现Ajax最好的方法,因为这段代码在任何支持Javascript浏览器上都可以使用,我想应该不会和暗门有关系吧)
编译,运行.........
在运行的页面上点击那个多选框就会显示 “___I call Server is succeed.___”。这个到底是如果执行的呢?其实只要在这个页面上点击“查看源代码”就可以了,这里隐藏着一个小秘密,在页面上自动生成了三段脚本块,一个是__doPostback这是一个用来处理服务器控件事件回发的,另外一个是我们刚才使用ClientScript注册的CallSerer方法,还有一个外部脚本的链接标记,这个就是关键所在,看它连接的URL指向是:
<script src="/TechTest/WebResource.axd?d=DE9YrizlDDq8OUlo_3rQgA2&t=632919546726295408" type="text/javascript"></script>
按照上面SRC指示的地址打开地址, 可以得到一个WebResource.axd的文件(把连接地址填到迅雷之类的下载工具里面就可以下载到了),打开就可以看到这个文件里面其实就是一些Javascript代码:
try
{
xmlRequest = new XMLHttpRequest();
}
catch(e)
{
try
{
xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e)
{
}
}
好眼熟的代码啊!
if (!useAsync)
{
if (__synchronousCallBackIndex != -1)
{
__pendingCallbacks[__synchronousCallBackIndex] = null;
}
__synchronousCallBackIndex = callbackIndex;
}
这个里面的?这不就是处理Page.ClientScript.GetCallbackEventReference方法中的异步调用选项的吗?
里面都是多多的有用代码,本人研究中.......................
除了这些里面还有很多方法,说白了就是一个很简单的Ajax框架的封装,有处理控件事件的有处理回发请求的,我们可以在这个基础上做另外一些封装,这样就可以直接封装成简单的.NET的Ajax控件,作为开发中的对.NET的一个轻量级解决方案。
其实就是Java、.NET亦或是PHP技术,都是在服务器端对于HTTP的高级封装,就像很早以前我们使用的CGI技术,而现在的Web的技术封装的更为高级了一些,而了解到了.NET的内部运行机制,我们可以脱离一些限制,自己重写一部分页面或控件,来构建自己的Ajax开发环境。
本人原来是也是个控件工,我觉得封装是大工厂时代必须的一种技术,但是程序员还是要多的追根究底,真正的了解到程序运行背后的内容这样才能更好的开发出高质量的程序。
http://www.cnblogs.com/Jaffa/archive/2006/09/01/492303.html
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>- 跳出封装剖析ASP.NET脚本回调的原理
- 跳出封装剖析ASP.NET脚本回调的原理
- 跳出封装剖析ASP.NET脚本回调的原理
- 深入剖析ASP.NET的编译原理
- 深入剖析ASP.NET的编译原理之一:动态编译
- 深入剖析ASP.NET的编译原理之一:动态编译
- ASP.NET MVC Unobtrusive Ajax 原理剖析
- ASP.NET Core 运行原理剖析
- ASP.NET的原理
- [深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白
- ASP.NET 中的自定义脚本回调
- ASP.NET 中的自定义脚本回调
- ASP.NET 中的自定义脚本回调
- Asp.net 2.0 脚本回调技术
- ASP.NET 中的自定义脚本回调
- 深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
- [转]深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
- [转]深入剖析ASP.NET的编译原理之二:预编译(Precompilation)
- ASP.NET讲座(4)-数据绑定DataBind
- ASP.NET讲座(2)-ASP.NET控件
- ASP.NET讲座(3)-输入验证控件
- ASP.NET讲座(1)-ASP.NET简介
- 在ASP.NET代码里访问跟踪信息
- 跳出封装剖析ASP.NET脚本回调的原理
- 正则学习:组的定义及引用方式
- 字符自动截取问题
- AspNetForums的数据层概述
- ASP.NET生成RSSFeed
- ASP.NET页面事件
- Asp.Net的控件如何与Server交互
- 获取本机上配置好的Oracle服务名
- COOKIE问题