




已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
谈起Ajax做过web开发的都非常熟悉,就是通过xmlhttp request与服务器端通信而避免页面刷新。关于Ajax是如何运作的,网上有很多帖子解释其各js文件的作用及调用xmlhttp的原理。但Ajax到底是怎么调用服务器端的C#代码的呢?怎么让后台的方法运行并将结果反馈给xmlhttp的呢?曾经有个同事问起我这个问题,我还真懵了!本以为象.Net 1.1下通过form传递必要的EventName及EventPara等参数传给服务器端继而解析后执行对应的事件一样来调用C#代码的(.net调用事件机制也不全是这么回事,待探讨),但通过仔细研究,发现原来远不是这么回事,而网上更深入的文章却少之又少。我们由浅到深吧,先看看相对表象的东西,即前台Ajax相关的JavaScript代码部分。之所以说相对肤浅和表象,是因为这些资料很多网友已经撰文解读过。凡要使用AjaxPro,我们大致要做以下工作:1) 在项目中引用AjaxPro.dll(我用的是AjaxPro.2.dll,版本),并在web.config中httpHandlers配置节添加:2) 在要使用Ajax功能的页面.cs文件上注册Ajax,例如: protected void Page_Load(object sender, EventArgs e) / 注册Ajax AjaxPro.Utility.RegisterTypeForAjax(typeof(Default); 3) 在.cs文件中声明可以被Ajax调用的函数(或属性),如: AjaxPro.AjaxMethod public string GetChild(string parentId) return return value from .cs file; 4) 在.aspx文件中用JavaScript调用Ajax,如: var items = DynLoadTree.Default.GetChild( aa ).value; / 通过Ajax调用后台代码 alert(items); 做好以上四步,我们就基本实现了Ajax页面不刷新的功能了。那么它是怎样通过xmlhttp与服务器通讯的呢?运行后我们可以看到HTML文件的源代码多了几行.ashx文件的引用: 实际上这些.ashx就是在上面第2步AjaxPro.Utility.RegisterTypeForAjax注册Ajax时自动将这些引用添加到Html文档输出的。那这些文件是什么文件呢?再看第1步中在web.config中添加到httpHandlers节中的配置,它告诉系统凡是收到ajaxpro路径下已经ashx为后缀的请求就全部交给AjaxPro.AjaxHandlerFactory这个类来处理,而这些ashx经过处理后返回的就是一些JavaScript文件,和普通的js引用没有实质区别。我们首先看看“DynLoadTree.Default,DynLoadTree.ashx”的内容:if(typeof DynLoadTree = undefined) DynLoadTree=;DynLoadTree.Default_class = function() ;Object.extend(DynLoadTree.Default_totype, Object.extend(new AjaxPro.AjaxClass(), GetChild: function(parentId) return this.invoke(GetChild, parentId:parentId, this.GetChild.getArguments().slice(1);,url: /ajaxpro/DynLoadTree.Default,DynLoadTree.ashx);DynLoadTree.Default = new DynLoadTree.Default_class();原来我们DynLoadTree.Default是在这里定义的,而这个GetChild方法最终是调用“this.invoke(GetChild, parentId:parentId, this.GetChild.getArguments().slice(1);”的,而invoke方法是在“core.ashx”中定义的。在core.ashx中定义了很多Ajax核心的js方法,例如Object.extand实现简单的继承(或阅扩展)。在invoke方法里,首先是new了一个XmlHttp对象,然后重点做了几件事:this.xmlHttp.open(POST, this.url, async); this.xmlHttp.setRequestHeader(Content-Type, application/x-www-form-urlencoded); this.xmlHttp.setRequestHeader(X- + AjaxPro.ID + -Method, method); this.xmlHttp.send(json);xmlHttp.open说明了是向哪个服务器url发送请求,是同步请求还是异步请求。接下来就设置Content-Type的http header,然后再将method设置到http header中,以让服务器端知道要调用什么方法,最后send出去,同时参数json包含了调用这个方法所需的参数。至此,利用xmlhttp已经将请求发送给服务器了,接下来就等待服务器的反馈结果了(对于同步和异步不同的调用方式,对结果的处理是有区别的)。但是,为什么这样一个请求给服务器后,服务器就自动调用制定的method呢?如果仔细一点,你可以发现xmlHttp.open里的this.url到底是什么?是要调用的页面的地址么?实际不是,这个this.url的值是“/ajaxpro/DynLoadTree.Default,DynLoadTree.ashx”。第一次看到这里的时候,我很诧异,怎么这个xmlhttp请求也发给一个ashx文件了呢?难道ashx文件不仅仅是用来动态生成js文件的么?同上,在web.config中已经配置了凡是ashx文件都交由类AjaxPro.AjaxHandlerFactory来处理,要想明白其中的奥秘,还得看看AjaxHandlerFactory里到底都干了些什么。为此,我用Reflector对AjaxPro.2.dll文件进行反编译(我的资源里提供下载),看了AjaxHandlerFactory的代码才大彻大悟!原来,在AjaxHandlerFactory的GetHandler方法里是这么写的:public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) string str2 = requestType; if (str2 != null) if (!(str2 = GET) if (str2 = POST) if (!(!Utility.Settings.OnlyAllowTypesInList | flag) return null; IAjaxProcessor processorArray = new IAjaxProcessor new XmlHttpRequestProcessor(context, type), new IFrameProcessor(context, type) ; for (int i = 0; i 0) useAsyncProcessing = customAttributes0.UseAsyncProcessing; if (customAttributes0.RequireSessionState != HttpSessionStateRequirement.UseDefault) readWrite = customAttributes0.RequireSessionState; switch (readWrite) case HttpSessionStateRequirement.ReadWrite: if (useAsyncProcessing) return new AjaxAsyncHttpHandlerSession(processorArrayi); return new AjaxSyncHttpHandlerSession(processorArrayi); case HttpSessionStateRequirement.Read: if (useAsyncProcessing) return new AjaxAsyncHttpHandlerSessionReadOnly(processorArrayi); return new AjaxSyncHttpHandlerSessionReadOnly(processorArrayi); case HttpSessionStateRequirement.None: if (useAsyncProcessing) return new AjaxAsyncHttpHandler(processorArrayi); return new AjaxSyncHttpHandler(processorArrayi); if (!useAsyncProcessing) return new AjaxSyncHttpHandlerSession(processorArrayi); return new AjaxAsyncHttpHandlerSession(processorArrayi); else switch (fileNameWithoutExtension.ToLower() case prototype: return new EmbeddedJavaScriptHandler(prototype); case core: return new EmbeddedJavaScriptHandler(core); default: return new TypeJavaScriptHandler(type); return null;它首先对requestType进行判断,如果是“GET”请求,则说明是html里对被引用的ashx文件的下载请求,则调用相应的Handler去生成对应的JavaScript内容输出到客户端;如果是“POST”请求,则说明是通过XMLHTTP发送过来的,是请求调用服务器端方法的,则返回相应的Handler利用反射机制调用请求的方法。首先看看“GET”请求,对“GET”请求的处理很简单,根据不同的文件名返回不同的Handler,对于“core”及“prototype”则返回EmbeddedJavaScriptHandler,对于“DynLoadTree.Default,DynLoadTree.ashx”则返回TypeJavaScriptHandler。在EmbeddedJavaScriptHandler中,构造函数的参数表示要请求的是哪个文件,然后在ProcessRequest函数中提取指定的文件内容并输出到客户端,其实这些文件内容都是固定的,且已经放在资源里的:internal class EmbeddedJavaScriptHandler : IHttpHandler / Fields private string fileName; / Methods internal EmbeddedJavaScriptHandler(string fileName) this.fileName = fileName; public void ProcessRequest(HttpContext context) string strArray = this.fileName.Split(new char , ); Assembly executingAssembly = Assembly.GetExecutingAssembly(); for (int i = 0; i strArray.Length; i+) Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(AjaxPro.2. + strArrayi + .js); if (manifestResourceStream != null) StreamReader reader = new StreamReader(manifestResourceStream); context.Response.Write(reader.ReadToEnd(); context.Response.Write(rn); reader.Close(); if (strArrayi = prototype) & Utility.Settings.OldStyle.Contains(objectExtendPrototype) context.Response.Write(rnOtotype.extend = function(o, override) rntreturn Object.extend.apply(this, this, o, override != false);rnrn); 对于“DynLoadTree.Default,DynLoadTree.ashx”的请求,则交给TypeJavaScriptHandler处理:internal class TypeJavaScriptHandler : IHttpHandler, IReadOnlySessionState, IRequiresSessionState / Fields private Type type; / Methods internal TypeJavaScriptHandler(Type type); public void ProcessRequest(HttpContext context); / Properties public bool IsReusable get; ProcessRequest会根据Type动态生成JavaScript内容并输出到客户端。 对于requestType是“POST”的请求,则返回相应的Handler进行处理。以AjaxSyncHttpHandler为例:internal class AjaxSyncHttpHandler : IHttpHandler / Fields private IAjaxProcessor p; / Methods internal AjaxSyncHttpHandler(IAjaxProcessor p) this.p = p; public void ProcessRequest(HttpContext context) new AjaxProcHelper(this.p).Run(); / Properties public bool IsReusable get return false; 其中ProcessRequest方法就就新建一个AjaxProcHelper对象,用该对象的Run方法来处理实质请求。可以简略看看AjaxProcHelper.Run的代码:internal void Run() this.p.Context.Response.Expires = 0; this.p.Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); this.p.Context.Response.ContentType = this.p.ContentType; this.p.Context.Response.ContentEncoding = Encoding.UTF8; object args = null; object o = null; args = this.p.RetreiveParameters(); string key = string.Concat(new object this.p.Type.FullName, |, this.p.GetType().Name, |, this.p.AjaxMethod.Name, |, this.p.GetHashCode() ); if (this.p.Context.Cachekey != null) this.p.Context.Response.AddHeader(X-AjaxPro-Cache, server); this.p.Context.Response.Write(this.p.Context.Cachekey); else if (this.p.AjaxMethod.IsStatic) o = this.p.Type.InvokeMember(this.p.AjaxMethod.Name, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase, null, null, args); else object obj3 = Activator.CreateInstance(this.p.Type, new object0); o = this.p.AjaxMethod.Invoke(obj3, args); if (o != null) & (o.GetType() = typeof(XmlDocument) this.p.Context.Response.ContentType = text/xml; (XmlDocument) o).Save(this.p.Context.Response.OutputStream); 可以清晰的看到,Run中是通过反射机制调用相应的方法,再将结果写入context输出到客户端的。另外,我们也可以清晰的看到Utility中对RegisterTypeForAjax的几个重载及实现方式: public static void RegisterTypeForAjax(Type type); public static void RegisterTypeForAjax(Type type, Page page);同时,也可以看看AjaxMethodAttribute的定义(有关Attribute MSDN中有详细的描述和实例):AttributeUsage(AttributeTargets.Method, AllowMultiple=false)public class AjaxMethodAttribute : Attribute / Fields private HttpSessionStateRequirement requireSessionState; private bool useAsyncProcessing; / Methods public AjaxMethodAttribute(); public AjaxMethodAttribute(HttpSessionStateRequirement requireSessionState); Obsolete(The use of this argument is currently in beta state, please report any problems to bugschwarz-interactive.de.) public AjaxMethodAttribute(bool useAsyncProcessing); Obsolete(The recommended alternative is AjaxPro.AjaxServerCacheAttribute., true) public AjaxMethodAttribute(int cacheSeconds); Obsolete(The recommended alternative is AjaxPro.AjaxNamespaceAttribute., true) public AjaxMethodAttribute(string methodName); Obsolete(The use of this argument is currently in beta state, please report any problems to bugschwarz-interactive.de.) public AjaxMethodAttribute(HttpSessionStateRequirement requireSessionState, bool useAsyncProcessing); Obsolete(The recom
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 抖音短视频内容合作终止及版权归属确认协议
- 企业团体意外伤害险保单转移与续保协议
- 抖音企业号短视频创意制作与品牌传播合作协议
- 区块链智能合约版权保护审计及合规性审查协议
- 不宁腿综合征护理要点
- 护理教学组长职责
- 房地产开发流程全景图
- 医学生研究生面试准备与策略
- 第12课 近代战争与西方文化的扩张
- 2025版高中化学第三章第一节第1课时醇学案含解析新人教版选修5
- 【教学课件】第六章 熟悉而陌生的力 第一节 力 精品课件
- 国家开放大学(电大)《现代企业管理》形考、终考及答案
- 你好,无废校园主题班会
- (完整版)英语写作期末试题和答案解析
- 广西建设工程造价咨询服务行业收费参考标准
- 综合布线-r4.1-双绞线链路测试
- 图纸会审会议纪要范本
- GB∕T 17466.1-2019 家用和类似用途固定式电气装置的电器附件安装盒和外壳 第1部分:通用要求
- 钻探设备工具材料共12
- 得到上市招股书:北京思维造物信息科技股份有限公司
- 浅谈高速公路沥青混凝土路面桥头跳车几种处理措施
评论
0/150
提交评论