深入Atlas系列:客户端网络访问基础结构示例(1) - 编写并使用自定义的WebRequestExecutor

简介:
 WebRequestExecutor是ASP.NET AJAX网络访问基础结构的唯一修改点。理论上,我们可以使用自定义的WebRequestExecutor来取代默认的 XMLHttpExecutor。我们要做的,其实只是开发一个继承于Sys.Net.WebRequestExecutor类。不过事实上,在实际使用 中,Sys.Net.XMLHttpExecutor已经足够用了,真的要自定义,也只需继承这个类即可。就像接下去的例子一样。

  可 是,Sys.Net.XMLHttpExecutor作为一个父类来说,可以说相当的不友好。先不多说,我们开始吧。在这个例子中,我们将开发一个 TraceExecutor,如果使用了这个Executor,Request和Response的信息都会被打印在页面上,开发人员可以把这些内容作为 一个参考。TraceExecutor非常简单,代码也很短。

  首先,是构造函数代码。如下:
Jeffz.Net.TraceExecutor  =   function  Jeffz$Net$TraceExecutor()
{
    Jeffz.Net.TraceExecutor.initializeBase(
this );
}

  一般情况下,在这个方法中,会初始化所有的“私有”变量。不过在这里,我们不需要。

  然后,我们将覆盖XMLHttpExecutor的executeRequest方法,我们需要作的,就是将WebRequest对象打印在页面上。代码如下:
function  Jeffz$Net$TraceExecutor$executeRequest()
{
    debug.trace(
" <b>Request sent at  "   +   new  Date()  +   " :</b> " );
    debug.dump(
this .get_webRequest(),  " Request " );
    
    Jeffz.Net.TraceExecutor.callBaseMethod(
this " executeRequest " );
}

  我在这里使用Debug模式下,为方法起了一个“别名”,在prototype中需要使用一下。自然,我们也需要调用registerClass,表示类的继承关系。代码如下:
Jeffz.Net.TraceExecutor.prototype  =  
{
    executeRequest : Jeffz$Net$TraceExecutor$executeRequest
}
Jeffz.Net.TraceExecutor.registerClass('Jeffz.Net.TraceExecutor', Sys.Net.XMLHttpExecutor);

  等一下,为什么我们就覆盖executeRequest这一个方法呢?很显然,我们只是打印出了Request的信息,那么Response呢?我们是不是还需要再覆盖另一个方法呢?

  我们的确应该再写一些代码,用来将Response信息打印出来,但是我们的做法不是覆盖XMLHttpExecutor的另一个方法,原因有两点:
  • XMLHttpExecute作为一个父类,相当地不友好。可以从代码里看到,它用来相应XMLHttpRequest对象 onreadystatechanged的回调函数“_onReadyStateChanged”是定义在其构造函数内。也就是说,它又使用了 Closure,而不是prototype。这样我们事实上就无法覆盖那些方法了,如果要继续在TraceExecutor上面做文章的话,我们必须写大 量的代码,这几乎就相当于重新写了一个WebRequestExecutor。为什么会出现这种情况?是XMLHttpExecutor故意写成这个样的 吗?我们来看一下:在XMLHttpRequest代码的executeRequest方法中,设置XMLHttpRequest对象 onreadystatechanged的代码是:“this._xmlHttpRequest.onreadystatechanged = this._onReadyStateChanged”,然后在_onReayStateChanged方法中使用了保留在Closure之中的 “_this”变量。这个是没有“Function.createDelegate”时,或者在使用Closure时的写法,编写过Windows Live Gadget的朋友们可以回忆一下,在使用官方提供的模版时,是不是在一开始也保留了一个“m_this”变量?这是相似的原因。那么在 XMLHttpExecutor里,为什么不使用“Function.createDelegate”方法?估计只有负责这部分代码的开发人员才知道了。 因此,我认为这里部分使用了Closure不是故意所为,这更像是负责这段代码的开发人员一时“神志错乱”。
  • 即使我们覆盖了“_onReadyStateChanged”方法,我们还漏了一些别的。如果这个Request超时了呢?如果这个Request被abort了呢?如果我们一一覆盖这些方法的话,似乎也有些太麻烦了。

  因为上面两个原因(主要是第一个),我们将响应Sys.Net.WebRequestManager.completeRequest事件,在这个事件被触发时打印Response的信息。代码如下:
Jeffz.Net.TraceExecutor.traceResponse  =   function  Jeffz$Net$TraceExecutor$traceResponse(response)
{
    debug.trace(
" <b>Response received at  "   +   new  Date()  +   " :</b> " );
    debug.dump(response, 
" Response " );
}
Sys.Net.WebRequestManager.add_completedRequest(Jeffz.Net.TraceExecutor.traceResponse);

  我们可以尝试着使用一下,代码很简单,将HTML和Javascript一并贴出了。代码如下:
< asp:ScriptManager  runat ="server"  ID ="ScriptManager1" >
    
< Scripts >
        
< asp:ScriptReference Path = " Debug.js "   />
        
< asp:ScriptReference Path = " TraceExecutor.js "   />
    
</ Scripts >
</ asp:ScriptManager >

< asp:UpdatePanel  runat ="server"  ID ="UpdatePanel1" >
    
< Triggers >
        
< asp:AsyncPostBackTrigger  ControlID ="btnRefresh"   />
    
</ Triggers >
    
< ContentTemplate >
        
<% =  DateTime.Now.ToString( " r " %>
    
</ ContentTemplate >
</ asp:UpdatePanel >

< asp:Button  runat ="server"  ID ="btnRefresh"  Text ="Refresh" />

< script  language ="javascript" >
    Sys.Net.WebRequestManager.set_defaultExecutorType(
" Jeffz.Net.TraceExecutor " );
</ script >

  在这里,需要使用我在《 为ASP.NET AJAX 1.0 Beta补充trace和dump功能 》里提到的Debug.js来补充ASP.NET AJAX中缺少的trace和dump功能。在代码的最后会使用Javascript将默认的WebRequestExecutor设为Jeffz.Net.TraceExecutor。

  打开页面,点击Refresh按钮,嗯?Request信息不错,不过Response信息为什么只是这些?
Response {Jeffz.Net.TraceExecutor}
+_webRequest {Sys.Net.WebRequest}
+_resultObject: null
+_xmlHttpRequest {Object}
+_responseAvailable: true
+_timedOut: false
+_timer: null
+_aborted: false
+_started: true

  原因在于,由于缺少了了Type Descriptor,debug.dump方法只会将该对象上附属的“值”(例如:this._started)打印出来,而不会调用任何方法。而在 XMLHttpExecutor中,许许多多方法(各种属性的get方法)是直接将消息委托给XMLHttpRequest对象,而不是将信息保留在 XMLHttpExecutor附属“值”上,因此,我们得到的只能是这些无用的信息了。

  那么我们该怎么做?那么就为Response对象补充一个Type Descriptor。这里的Response对象其实就是Jeffz.Net.TraceExecutor类的实例,因此我们需要为该类添加一个Type Descriptor。代码如下:
Jeffz.Net.TraceExecutor.descriptor  =
{
    properties:
    [
        {name: 'started', type: Boolean },
        {name: 'timedOut', type: Boolean },
        {name: 'aborted', type: Boolean },
        {name: 'responseAvailable', type: Boolean },
        {name: 'responseData', type: String },
        {name: 'statusCode', type: Number },
        {name: 'statusText', type: String }
    ]
}

  这是RTM中Type Descriptor的表示方式。可以发现我在这里只添加了部分,而不是全部的属性。例如缺少了object属性,为什么呢?在XMLHttpExecutor中get_object方法是这样定义的:
function  Sys$Net$WebRequestExecutor$get_object() {
    
// / <value></value>
     if  (arguments.length  !==   0 throw  Error.parameterCount();

    
if  ( ! this ._resultObject) {
        
this ._resultObject  =  Sys.Serialization.JavaScriptSerializer.deserialize( this .get_responseData());
    }

    
return   this ._resultObject;
}

  我们可以发现,这段逻辑并没有判断responseData的合法性,如果它不是一个正确的JSON字符串,就会抛出异常。如果一定要在 Type Descriptor中定义object属性的话,那么我们还必须在TraceExecutor中覆盖XMLHttpRequest的object属性。 作为一个没有多少使用价值的演示,我们就不作得如此“仁至义尽”了。:)

  现在我们再来看一下打印出来的内容:



本文转自 jeffz 51CTO博客,原文链接:http://blog.51cto.com/jeffz/60685,如需转载请自行联系原作者

相关文章
|
10月前
|
网络协议 Linux 虚拟化
配置VM网络:如何设定静态IP以访问主机IP和互联网
以上就是设定虚拟机网络和静态IP地址的基本步骤。需要注意的是,这些步骤可能会因为虚拟机软件、操作系统以及网络环境的不同而有所差异。在进行设定时,应根据具体情况进行调整。
653 10
|
机器学习/深度学习 编解码 TensorFlow
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
869 0
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
599 61
|
11月前
|
Shell 开发工具 git
使用代理访问网络各项命令总结
工作中常需设置代理,容易导致环境混乱。本文总结了 SourceTree 无法拉取代码的问题,排查了环境变量、Git 全局配置及系统代理设置,最终通过清除 Git 代理配置解决。内容涵盖排查步骤、命令整理及脚本处理,帮助快速定位并解决代理相关网络问题。
695 3
|
机器学习/深度学习 自动驾驶 计算机视觉
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构
777 61
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构
|
运维 网络协议 Go
Go网络编程:基于TCP的网络服务端与客户端
本文介绍了使用 Go 语言的 `net` 包开发 TCP 网络服务的基础与进阶内容。首先简述了 TCP 协议的基本概念和通信流程,接着详细讲解了服务端与客户端的开发步骤,并提供了简单回显服务的示例代码。同时,文章探讨了服务端并发处理连接的方法,以及粘包/拆包、异常检测、超时控制等进阶技巧。最后通过群聊服务端的实战案例巩固知识点,并总结了 TCP 在高可靠性场景中的优势及 Go 并发模型带来的便利性。
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
1182 12
|
域名解析 监控 网络协议
21.7K star!再见吧花生壳,没有公网ip,也能搞定所有网络访问!内网穿透神器NPS
“nps”是一款强大的内网穿透工具,支持多种协议与功能。它无需公网IP或复杂配置,可实现远程桌面、文件共享和私有云搭建等。项目采用Go语言开发,具有高性能与轻量级特点,适用于远程办公、物联网管理等场景。其核心亮点包括零配置穿透、多级代理网络、实时流量监控及企业级安全特性。对比同类工具,“nps”在安装复杂度、协议支持和管理界面方面表现优异。项目地址:https://github.com/ehang-io/nps。
3070 12
|
Ubuntu 网络协议 Unix
02理解网络IO:实现服务与客户端通信
网络IO指客户端与服务端通过网络进行数据收发的过程,常见于微信、QQ等应用。本文详解如何用C语言实现一个支持多客户端连接的TCP服务端,涉及socket编程、线程处理及通信流程,并分析“一消息一线程”模式的优缺点。
660 0
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
621 20

热门文章

最新文章