zoukankan      html  css  js  c++  java
  • ASP.NET AJAX(8)__Microsoft AJAX Library中异步通信层的使用

    什么是异步通信层

    • Microsoft AJAX Library的组长部分之一
    • 负责ASP.NET AJAX框架中所有的客户端与服务器端的通信
    • 其默认实现了封装了XMLHttpRequest的功能
    一个使用XMLHttpRequest发出AJAX请求的示例

    创建一个名为RandomNumber.ashx的一般处理程序

    <%@ WebHandler Language="C#" Class="RandomNumber" %>
    
    using System;
    using System.Web;
    
    public class RandomNumber : IHttpHandler 
    {
        private static Random random = new Random(DateTime.Now.Millisecond);
        
        
        public void ProcessRequest (HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write(random.Next());
        }
     
        public bool IsReusable
        {
            get 
            {
                return false;
            }
        }
    
    }
     

    创建一个htm页面

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <script language="javascript" type="text/javascript">
            function getXMLHttpRequest() {//获得XMLHttpRequest对象
                if (window.XMLHttpRequest) {//如果有原生的XMLHttpRequest,IE6+、firefox都有
                    return new window.XMLHttpRequest();
                }
                else {//如果没有原生的XMLHttpRequest
                    var progIDs = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'];
                    for (var i = 0; i < progIDs.length; i++) {
                        try {
                            var xmlHttp = new ActiveXObject(progIDs[i]);
                            return xmlHttp;
                        } 
                        catch (ex) { }
                    }
                    return null;
                }
            }
    
            function sendRequest() {
                var xhr = getXMLHttpRequest();
                //第一个参数:发送请求的方式。第二个参数:请求发给的地址。第三个参数:true异步更新(默认),false阻塞更新
                xhr.open("POST", "RandomNumber.ashx", true);
                xhr.onreadystatechange = function() {//指定回调函数
                    onReadyStateChange.apply(xhr);//将xhr作为this指针
                }
                xhr.send(null);//发送请求,参数为请求的body
            }
            
            function onReadyStateChange() {
                if (this.readyState == 4) {//readyState==4表示得到结果
                    if (this.status == 200) {//status==200表示得到结果正常
                        alert(this.responseText);
                    }
                }
                else {
                    
                }
            }
        </script>
    </head>
    <body>
        <input type="button" value="Send" onclick="sendRequest()" />
    </body>
    </html>

    注释中我已经写的很清楚,XMLHttpRequest在当他的readyState改变以后,调用我们定义的onReadyStateChange,然后通过判断一些状态来验证是否得到了我们想要数据,而不是服务器端抛出的错误等等

    Micorsoft AJAX Library异步通信层的组成

    • 均在Sys.Net命名空间下
    • WebRequest类:负责手机存储请求信息
    • WebRequestExecutor类:负责发送请求,反馈服务器端回复的结果
    • WebRequestManager类:用户管理异步通讯层与服务器端的通信

      WebRequest类成员

    • completed事件:得到回复后出发
    • completed方法:引发completed事件
    • getResolvedUrl方法:获得完整的URL
    • invoke方法:发送请求
    • body属性:发送到服务器的内容
    • executor属性:发送请求的Executor对象
    • headers属性:请求的头信息集合
    • httpVerb属性:请求使用的HTTP方法
    • timtout属性:超时时间
    • url属性:请求的URL
    • userContext属性:附加于WebRequest的对象

           WebRequestExexutor成员

    • abort方法:取消当前请求
    • executorRequest方法:执行请求
    • getAllResponseHeaders方法:获取回复内所有的头文件
    • getResponseHeader方法:获得回复指定的头信息
    • aborted属性:表示请求是否被取消
    • responseAvailable属性:表示是否得到了正确的结果
    • responseData属性:获得字符串形式的回复内容
    • started属性:表示请求是否已经开始
    • statusCode属性:表示回复状态的代码
    • statusText属性:表示回复状态的文字
    • timedOut属性:表示是否超时
    • xml属性:获得xml形式的回复内容
    • webRequest属性:获得当前正在执行的WebRequest对象
    使用异步通信层的示例

    首先创建一个名为Complex.ashx的一般处理程序

    <%@ WebHandler Language="C#" Class="Complex" %>
    
    using System;
    using System.Web;
    
    public class Complex : IHttpHandler
    {
    
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
    
            string action = context.Request.Headers["action"];//得到Header中key为action的值
            if (action == "normal")
            {
                context.Response.Write("You've sent:" + context.Request.Params["data"]);//把传过来的data值做处理,然后写回
            }
            else if (action == "error")
            {
                throw new Exception();//抛出一个异常
            }
            else
            {
                System.Threading.Thread.Sleep(5000);//线程停止5秒,如果客户端设置超时小于五秒,则会造成一个超时错误
            }
        }
    
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    
    }
     

    然后创建一个aspx页面

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <script language="javascript" type="text/javascript">
            var webRequest=null;
            function sendRequest(action) {
                webRequest = new Sys.Net.WebRequest();
                webRequest.set_url("Complex.ashx");//设置请求路径
                webRequest.get_headers()["action"] = action;//设置一个key为action的Header
                webRequest.set_body("data=" + encodeURIComponent("Xiaoyaojian"));//设置发送的内容
                webRequest.set_httpVerb("POST");//设置请求使用的HTTP方法
                webRequest.set_timeout(3000);//设置超时时间
    
                webRequest.add_completed(onCompleted);//添加完成时候的回调函数 
                webRequest.invoke();//执行请求
            }
    
            function onCompleted(response, eventArgs) {
                if (response.get_aborted()) {//判断是否被取消
                    alert("Request aborted!");
                }
                else if (response.get_responseAvailable()) {//判断得到的信息是否正确
                    var statusCode = response.get_statusCode();//得到状态码
                    if (statusCode < 200 || statusCode >= 300) {//状态码小于200或者大于等于300,则表示出现了错误
                        alert("Error occurred!");
                    }
                    else {
                        alert(response.get_responseData());//回复的信息
                    }
                }
                else {
                    if (response.get_timedOut()) {//判断是否为超时
                        alert("Request timed out!");
                    }
                    else {
                        alert("Error occurred!");
                    }
                }
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
            
            <input type="button" value="Normal" onclick="sendRequest('normal');" />
            <input type="button" value="Error" onclick="sendRequest('error');" />
            <input type="button" value="Time out" onclick="sendRequest('ad');" />
            <input type="button" value="Abort" onclick="webRequest.get_executor().abort()" />
        </form>
    </body>
    </html>

    点击Normal,得到正常的结果,点击Error,出现一个错误,点击Time out,得到一个超时错误,点击Abort,可以取消一个请求,我们可以使用先点击Time out,然后在三秒内点击Abort来得到一个取消的效果

                      WebRequestManager成员

    • invokingRequest事件:即将发送请求时候触发,可用于取消某个请求
    • completedRequest事件:请求结束时候触发,他早于WebRequest对象的completed事件
    • defaultTimeout属性:默认超时时间
    • defaultExecutorType属性:默认的发送请求的Executor类型
    使用WebRequestManager的事件的示例

    创建一个aspx页面

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
                    <%= DateTime.Now %><hr />
                    <asp:Button ID="Button1" runat="server" Text="Button" />
                </ContentTemplate>
            </asp:UpdatePanel>
            
            <script language="javascript" type="text/javascript">
                Sys.Net.WebRequestManager.add_invokingRequest(function(sender, eventArgs) {
                if (confirm("Concel the partial rendering?")) {//在即将发起请求的时候,参数提示,让用户确认
                    eventArgs.set_cancel(true);//取消操作
                        
                    }
                });
    
                Sys.Net.WebRequestManager.add_completedRequest(function() {//在请求结束以后,WebRequest的completed没有被触发之前,给出一个提示
                    alert("Response received!");
                });
            </script>
        </form>
    </body>
    </html>
     
     

    示例简单的。。。我都不知道该说什么了,就是响应了WebRequestManager的两个事件。。。。。。

    WebRequestExecutor类成员

    • abort方法:取消当前操作
    • executeRequest方法:执行请求
    • getAllResponseHeaders方法:获取回复中所有的头信息
    • getResponseHeader方法:获取回复中指定KEY的头信息
    • aborted属性:表示请求是否被取消
    • responseAvailable属性:表示是否得到了正确的结果
    • responseData属性:获得字符串形式的回复内容
    • started属性:表示请求是否已经开始
    • statusCode属性:表示回复状态代码
    • statusText属性:表示回复状态的问题
    • timedOut属性:表示回复是否为超时
    • xml属性:获得xml形式的回复内容
    • webRequest属性:获得当前正在执行的WebRequest对象

    实现ScriptReferenceExecutor

    • 实现简单属性(aborted,responseAvailable,responseData,started,statusCode,statusText,timedOut,xml)
    • 实现executeRequest方法(发送信息,监听超时)
    • 实现完成、超时、取消逻辑
    • 清楚超时监听和其他一些辅助对象
    • 调用WebRequest的completed方法
    • 实现不支持的方法:getAllResponseHeaders方法,getResponseHeader方法
    一个实现executeRequest方法的示例

    首先创建一个名为ScriptRerenceExcutor.js的js文件

    Sys.Net.ScriptReferenceExecutor = function() {//构造函数
        Sys.Net.ScriptReferenceExecutor.initializeBase(this);//调用基类的构造函数
        //初始化一些私有的变量
        this._responseAvailable = false;
        this._timedOut = false;
        this._aborted = false;
        this._started = false;
        this._responseData = null;
        this._statusCode = 0;
        this._statusText = null;
    
        this._uniqueKey = null;
        this._timer = null;
        this._scriptElement = null;
    
    }
    Sys.Net.ScriptReferenceExecutor.prototype =
    {
        //定义一些简单属性
        get_responseAvailable: function() {
            return this._responseAvailable;
        },
    
        get_timedOut: function() {
            return this._timedOut;
        },
    
        get_aborted: function() {
            return this._aborted;
        },
    
        get_started: function() {
            return this._started;
        },
    
        get_responseData: function() {
            return this._responseData;
        },
    
        get_statusCode: function() {
            return this._statusCode;
        },
    
        get_statusText: function() {
            return this._statusText;
        },
        //把get_responseData()得到的结果,然后进行XML转换
        get_xml: function() {
            return new XMLDOM(this.get_responseData());
        },
        
        executeRequest: function() {
            this._started = true;//表示执行已经开始
    
            var request = this.get_webRequest();//得到webRequest对象的信息
            var serializer = Sys.Serialization.JavaScriptSerializer;//Microsoft AJAX Library提供给我们进行JSON序列化和反序列化的方法
                    
            //以下是拼接QueryString的过程
            var scriptUrl = request.get_url() + "?";
            scriptUrl += (("headers=") + encodeURIComponent(serializer.serialize(request.get_headers())));
            scriptUrl += ("&body=" + encodeURIComponent(serializer.serialize(request.get_body())));
    
            var uniqueKey = this._uniqueKey = this._generateUniqueKey();//此字段确定加载的SciptRequestExecutor是由谁发起的
            scriptUrl += ("&uniqueKey=" + encodeURIComponent(serializer.serialize(uniqueKey)));
            Sys.Net.ScriptReferenceExecutor._executors[uniqueKey] = this; //把字的uniqueKey保存起来
    
            var scriptElement = this._scriptElement = document.createElement("script");
            scriptElement.type = "text/javascript";
            scriptElement.language = "javascript";
            scriptElement.src = scriptUrl;
            document.getElementsByTagName("head")[0].appendChild(scriptElement);
    
            //设置超时
            var timeout = request.get_timeout();
            if (timeout > 0) {
                this._timer = window.setTimeout(
                    Function.createDelegate(this, this._onTimeout), timeout);
            }
    
        },
    
        _onTimeout: function() {//设置超时执行的操作
            this.complete(null, null, null, false, true, false);
        },
    
        abort: function() {//设置取消操作后执行的操作
            this.complete(null, null, null, false, false, true);
        },
    
        _generateUniqueKey: function() {
            return Math.random().toString();//通常已经足够使用,当然还是可以采用其他一些更严格的做法
        },
    
        complete: function(statusCode, statusText, body, responseAvailable, timedOut, aborted) {
            this._statusCode = statusCode;
            this._statusText = statusText;
            this._responseData = body;
            this._responseAvailable = responseAvailable;
            this._timedOut = timedOut;
            this._aborted = aborted;
    
            if (this._timer) {
                window.clearTimeout(this._timer);
            }
            document.getElementsByTagName("head")[0].removeChild(this._scriptElement);
            delete Sys.Net.ScriptReferenceExecutor._executors[this._uniqueKey];
    
            this.get_webRequest().completed(Sys.EventArgs.Empty);
        }
    }
    Sys.Net.ScriptReferenceExecutor.registerClass("Sys.Net.ScriptReferenceExecutor", Sys.Net.WebRequestExecutor);
    Sys.Net.ScriptReferenceExecutor._executors = new Object();
    Sys.Net.ScriptReferenceExecutor.complete = function(uniqueKey, statusCode, statusText, body) {
        var executor = Sys.Net.ScriptReferenceExecutor._executors[uniqueKey];
        if (executor) {
            executor.complete(statusCode, statusText, body, true, false, false);
        }
    }

    然后创建一个名为ScriptReferenceExecutor.ashx的一般处理程序

    <%@ WebHandler Language="C#" Class="ScriptReferenceExecutor" %>
    
    using System;
    using System.Web;
    using System.Web.Script.Serialization;
    using System.Collections.Generic;
    
    public class ScriptReferenceExecutor : IHttpHandler 
    {
        
        public void ProcessRequest (HttpContext context) 
        {
            context.Response.ContentType = "text/plain";
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            Dictionary<string, string> headers = serializer.Deserialize<Dictionary<string, string>>(context.Request.QueryString["headers"]);
            string body = serializer.Deserialize<string>(context.Request.QueryString["body"]);
            string uniqueKey = serializer.Deserialize<string>(context.Request.QueryString["uniqueKey"]);
    
            string action = headers["action"];
            if (action == "normal")
            {
                this.SendResponse(context, uniqueKey, 200, "OK", "You've send: " + body);
            }
            else if (action == "error")
            {
                this.SendResponse(context, uniqueKey, 500, "Error", null);
            }
            else
            {
                System.Threading.Thread.Sleep(5000);
            }
        }
    
        private void SendResponse(HttpContext context, string uniqueKey, int statusCode, string statusText, string body)
        {
            context.Response.Write("Sys.Net.ScriptReferenceExecutor.complete('" + uniqueKey + "', ");
            context.Response.Write("'" + statusCode + "', ");
            context.Response.Write("'" + statusText + "', ");
            context.Response.Write(new JavaScriptSerializer().Serialize(body) + ");");
        }
        
        public bool IsReusable 
        {
            get 
            {
                return false;
            }
        }
    
    }

    然后创建一个aspx页面,引入我们创建的js文件

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <script language="javascript" type="text/javascript">
            var webRequest=null;
            function sendRequest(action) {
                webRequest = new Sys.Net.WebRequest();
                webRequest.set_url("ScriptReferenceExecutor.ashx"); //设置请求路径
                webRequest.get_headers()["action"] = action;//设置一个key为action的Header
                webRequest.set_body("data=" + encodeURIComponent("Xiaoyaojian"));//设置发送的内容
                webRequest.set_httpVerb("POST");//设置请求使用的HTTP方法
                webRequest.set_timeout(3000);//设置超时时间
    
                webRequest.set_executor(new Sys.Net.ScriptReferenceExecutor());
                
                webRequest.add_completed(onCompleted);//添加完成时候的回调函数 
                webRequest.invoke();//执行请求
            }
    
            function onCompleted(response, eventArgs) {
                if (response.get_aborted()) {//判断是否被取消
                    alert("Request aborted!");
                }
                else if (response.get_responseAvailable()) {//判断得到的信息是否正确
                    var statusCode = response.get_statusCode();//得到状态码
                    if (statusCode < 200 || statusCode >= 300) {//状态码小于200或者大于等于300,则表示出现了错误
                        alert("Error occurred!");
                    }
                    else {
                        alert(response.get_responseData());//回复的信息
                    }
                }
                else {
                    if (response.get_timedOut()) {//判断是否为超时
                        alert("Request timed out!");
                    }
                    else {
                        alert("Error occurred!");
                    }
                }
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server">
                <Scripts>
                    <asp:ScriptReference Path="~/Demo07/ScriptRerenceExcutor.js" />
                </Scripts>
            </asp:ScriptManager>
            
            <input type="button" value="Normal" onclick="sendRequest('normal');" />
            <input type="button" value="Error" onclick="sendRequest('error');" />
            <input type="button" value="Time out" onclick="sendRequest('ad');" />
            <input type="button" value="Abort" onclick="webRequest.get_executor().abort()" />
        </form>
    </body>
    </html>

    这样。我们就成功的使用了自定义的Executor

  • 相关阅读:
    php环境搭建
    Tomcat配置
    Android短信监听软件
    SASS官方文档
    HTML5 Shiv – 让该死的IE系列支持HTML5吧
    15+ 易响应的CSS框架快速开启你的敏捷网站项目
    遍历~树遍历~find()-next()-nextAll()-nextUntil()-parent()-parents()-parentsUntil()-prev()-prevAll()-prevUntil()-siblings()
    让IE支持@media 响应式布局
    遍历~树遍历~addBack();children();closest()
    遍历~筛选~eq();filter();first();last();has();is();map();slice()
  • 原文地址:https://www.cnblogs.com/xiaoyaojian/p/2218335.html
Copyright © 2011-2022 走看看