zoukankan      html  css  js  c++  java
  • 用httpHandler实现简易ajax框架

    前言:

      工作中常常用到以前同事写的一个ajax框架,偶尔抽空看看,感觉恩是复杂,于是自己花心思研究了一个比较简单的,使用httpHandler和反射实现的简易ajax框架。帖出此文,以此铭记,好好学习,天天向上……

    步骤一:

      首先需要一个接受客户端请求的httpHandler服务,我定义为"AjaxHandler",实现接口"IHttpHandler"和"IRequiresSessionState",有关这两个接口,在此不赘述,有兴趣请翻阅MSDN。

      实现一个属性"IsReusable" ,代码如下

      

            public bool IsReusable
            {
                get { return false; }
            }
    

      和一个方法"ProcessRequest",用以接受请求。 在这个方法内,我对请求参数头作了如下规定(即Request.Headers):

        键     值     含义

      InvokeType  Ajax   表示请求方式 为 Ajax 请求 目前只支持该请求,有兴趣的朋友可以实现其他的方式

      assembly   字符串 表示要请求的服务器方法所在类所在的程序集完全限定名(如:AjaxTest)

      space      字符串 表示要请求的服务器方法所在类所在的命名空间(如:Dxy.AjaxTest)

      className   字符串 表示要请求的服务器方法所在类的类名称(如:OrderHelper)

      methodName 字符串 表示要请求的服务器方法名称(如:GetOrders)

      代码如下:

      

    string assembly = request.Headers["assembly"]??"";
                string space = request.Headers["space"] ?? "";
                string className = request.Headers["className"] ?? "";
                string methodName = request.Headers["methodName"] ?? "";
                //if (assembly == "") throw new Exception("assembly can not be empty.");
                if (space == "") throw new Exception("namespace can not be empty.");
                if (className == "") throw new Exception("type can not be empty.");
                if (methodName == "") throw new Exception("method can not be empty.");
                Type type = Type.GetType(space + "." + className + "," + assembly);
                if (type != null)
                {
                    MethodInfo method = type.GetMethod(methodName);
                    if (method != null)
                    {
                        object[] arguments = null;
                        ParameterInfo[] parms = method.GetParameters();
                        if (parms.Length>0)
                        {
                            arguments = new object[parms.Length];
                            for (int i = 0; i < parms.Length; i++)
                            {
                                arguments[i] = Convert.ChangeType(request.Form[i], parms[i].ParameterType);
                            }
                        }
                        /* 判断调用的方法是否静态方法。
    					 * 如果是静态方法,则方法调用不需创建类实例。*/
                        object inst = method.IsStatic ? null : Activator.CreateInstance(type, true);
                        if (method.ReturnType.Name == "Void")
                        {
                            method.Invoke(inst, arguments);
                            return "";
                        }
                        else
                        {
                            return System.Web.HttpUtility.UrlEncode(method.Invoke(inst, arguments).ToString());
                        }
                    }
                    else
                    {
                        throw new Exception("method invoke failed.");
                    }
                }
                else
                {
                    throw new Exception("type invoke failed.");
                }
    

      整体代码如下:

      

    using System;
    using System.Web;
    using System.Web.SessionState;
    using System.Reflection;
    
    namespace AjaxFramework
    {
        public class AjaxHandler : IHttpHandler, IRequiresSessionState
        {
            #region IHttpHandler 成员
    
            public bool IsReusable
            {
                get { return false; }
            }
    
            public void ProcessRequest(HttpContext context)
            {
                try
                {
                    if (context.Request.Headers["InvokeType"] == "Ajax")
                    {
                        context.Response.Write(InvokeMethod(context.Request));
                    }
                }
                catch (Exception ex)
                {
                    context.Response.Write(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ex));
                }
                finally
                {
                    try
                    {
                        context.Response.End();
                    }
                    catch { }
                }
            }
    
            #endregion
            /// <summary>
            /// 处理ajax请求
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            private string InvokeMethod(HttpRequest request)
            {
                string assembly = request.Headers["assembly"]??"";
                string space = request.Headers["space"] ?? "";
                string className = request.Headers["className"] ?? "";
                string methodName = request.Headers["methodName"] ?? "";
                //if (assembly == "") throw new Exception("assembly can not be empty.");
                if (space == "") throw new Exception("namespace can not be empty.");
                if (className == "") throw new Exception("type can not be empty.");
                if (methodName == "") throw new Exception("method can not be empty.");
                Type type = Type.GetType(space + "." + className + "," + assembly);
                if (type != null)
                {
                    MethodInfo method = type.GetMethod(methodName);
                    if (method != null)
                    {
                        object[] arguments = null;
                        ParameterInfo[] parms = method.GetParameters();
                        if (parms.Length>0)
                        {
                            arguments = new object[parms.Length];
                            for (int i = 0; i < parms.Length; i++)
                            {
                                arguments[i] = Convert.ChangeType(request.Form[i], parms[i].ParameterType);
                            }
                        }
                        /* 判断调用的方法是否静态方法。
    					 * 如果是静态方法,则方法调用不需创建类实例。*/
                        object inst = method.IsStatic ? null : Activator.CreateInstance(type, true);
                        if (method.ReturnType.Name == "Void")
                        {
                            method.Invoke(inst, arguments);
                            return "";
                        }
                        else
                        {
                            return System.Web.HttpUtility.UrlEncode(method.Invoke(inst, arguments).ToString());
                        }
                    }
                    else
                    {
                        throw new Exception("method invoke failed.");
                    }
                }
                else
                {
                    throw new Exception("type invoke failed.");
                }
            }
        }
    }
    
    

    步骤二:

      将配置文件添加节点,用以指向前面定义的"AjaxHandler"

      代码如下:

    <httpHandlers>
    			<remove verb="*" path="*.asmx"/>
    			<add verb="*" path="*.dxy" validate="false" type="AjaxFramework.AjaxHandler"/>
    </httpHandlers>
    

      在这里我规定,凡是后缀为".dxy"的请求都指向"AjaxHandler"时间处理程序。

    步骤三:

      客户端请求脚本。 ajax核心XMLHttpRequest的创建与请求发送脚本。

      代码如下:

    //XMLHttpRequest
    ///<summary>创建XMLHttpRequest实例</summary>
    function CreateAjax() {
        var xmlHttp;
        if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        }
        else if (window.ActiveXObject) {
            try {
                xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) {
                try {
                    xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
                } catch (e) {
    
                }
            }
        }
        return xmlHttp;
    }
    var onInitf; //开始发送请求事件
    var onCompletef; //请求完成事件
    var onErrorf; //请求失败事件
    ///<summary>向服务器请求数据</summary>
    ///<param name="assembly">程序集</param>
    ///<param name="space">命名空间</param>
    ///<param name="className">类</param>
    function AjaxRequest(assembly, space, className) {
        var xmlHttp = CreateAjax();
        ///<param name="methodName">方法</param>
        ///<param name="args">参数数组</param>
        ///<param name="onInit">开始发送请求事件</param>
        ///<param name="onComplete">请求完成事件</param>
        ///<param name="onError">请求失败事件</param>
        this.sendRequest = function(methodName, args, onInit, onComplete, onError) {
            onInitf = onInit;
            onCompletef = onComplete;
            onErrorf = onError;
            xmlHttp.open("POST", "a.dxy"); //以POST方法请求服务器
            xmlHttp.setRequestHeader("InvokeType", "Ajax");
            xmlHttp.setRequestHeader("assembly", assembly);
            xmlHttp.setRequestHeader("space", space);
            xmlHttp.setRequestHeader("className", className);
            xmlHttp.setRequestHeader("methodName", methodName);
            xmlHttp.onreadystatechange = function() {
                switch (xmlHttp.readyState) {
                    case 0:
                        //此处可添加对用户提示的等待信息(如进度条)
                        if (typeof (onInit) == "function") {
                            onInitf();
                        }
                        break;
                    case 4:
                        //状态==200表示成功
                        if (xmlHttp.status == 200) {
                            try {
                                onCompletef(parseJson(xmlHttp.responseText));
                            } catch (e) {
                                onErrorf(e);
                            }
                        } else {
                            var e = parseJson(xmlHttp.responseText);
                            if (e == null) {
    //                            e = "{\"Message\":\"服务未找到。\"}";
                                e = parseJson("{\"Message\":\"服务未找到。\"}");
                            }
                            onErrorf(e);
                        }
                        break;
                }
            }
            xmlHttp.send(args);
    
            this.sendRequest.assembly = assembly;
            this.sendRequest.space = space;
            this.sendRequest.className = className;
            this.sendRequest.methodName = methodName;
        }
    }
    function parseJson(str) {
        if (typeof (str) == 'string' && str != null) {
            str = decodeURIComponent(str);
            try { return eval('(' + str.replace(/\r/g, '\\r').replace(/\n/g, '\\n') + ')'); }
            catch (e) { return null; }
        }
        return null;
    }
    

      我在其中公开了一个类型AjaxRequest,该类型包含一个实例函数sendRequest,外部调用只需要new一个AjaxRequest对象,然后调用方法传入相应的参数即可。 调用代码如下:

    <script language="javascript" type="text/javascript">
            function GetOrders() {
                var ajax = new AjaxRequest("AjaxTest", "Dxy.AjaxTest", "OrderHelper");
                var methodName = "GetOrders";
    
                ajax.sendRequest(methodName, null, null, function(data) {
                    var tab = document.createElement("table");
                    tab.style.width = "400px";
                    tab.style.height = "300px";
                    //创建table头部
                    var hr = tab.insertRow(0);
                    var htd0 = hr.insertCell(0);
                    htd0.innerHTML = "订单编号";
                    var htd1 = hr.insertCell(1);
                    htd1.innerHTML = "订单日期";
                    var htd2 = hr.insertCell(2);
                    htd2.innerHTML = "代理商";
                    var htd3 = hr.insertCell(3);
                    htd3.innerHTML = "金额";
                    //填充table内容
                    for (var i = 0; i < data.length; i++) {
                        var row = tab.insertRow(i + 1);
                        var td0 = row.insertCell(0);
                        td0.innerHTML = data[i].OrderID;
                        var td1 = row.insertCell(1);
                        td1.innerHTML = data[i].OrderTime;
                        var td2 = row.insertCell(2);
                        td2.innerHTML = data[i].Proxy;
                        var td3 = row.insertCell(3);
                        td3.innerHTML = data[i].Amount;
                    }
                    document.getElementById("divTest").appendChild(tab);
                }, function(e) {
                    alert("Ajax错误:" + e.Message);
                });
            }
        </script>
    

    步骤四:

      最后,我写了一个用来测试这个简易ajax框架的服务器后台类和页面。

      后台测试类代码如下:

    using System;
    using System.Collections.Generic;
    
    namespace Dxy.AjaxTest
    {
        public class Order
        {
            public string OrderID;
            public string OrderTime;
            public string Proxy;
            public double Amount;
        }
        public class OrderHelper
        {
            public string GetOrders()
            {
                List<Order> list = new List<Order>();
                list.Add(new Order()
                {
                    OrderID=Guid.NewGuid().ToString(),
                    Amount=1111,
                    OrderTime = DateTime.Now.ToString("yyyy-MM-dd"),
                    Proxy="神经病1号"
                });
                list.Add(new Order()
                {
                    OrderID = Guid.NewGuid().ToString(),
                    Amount = 2222,
                    OrderTime = DateTime.Now.ToString("yyyy-MM-dd"),
                    Proxy = "神经病2号"
                });
                list.Add(new Order()
                {
                    OrderID = Guid.NewGuid().ToString(),
                    Amount = 3333,
                    OrderTime = DateTime.Now.ToString("yyyy-MM-dd"),
                    Proxy = "神经病3号"
                });
                return new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(list);
            }
        }
    }
    
    

      页面前台代码如下:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AjaxFramework._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></title>
    <style type="text/css">
        table 
        {
            border-top:solid 1px gray;
            border-left:solid 1px gray;
            padding:0px;
            margin:0px;
        }
        table td
        {
            border-right:solid 1px gray;
            border-bottom:solid 1px gray;
        }
    </style>
        <script src="JavaScript/Ajax.js" type="text/javascript"></script>
    
        <script language="javascript" type="text/javascript">
            function GetOrders() {
                var ajax = new AjaxRequest("AjaxTest", "Dxy.AjaxTest", "OrderHelper");
                var methodName = "GetOrders";
    
                ajax.sendRequest(methodName, null, null, function(data) {
                    var tab = document.createElement("table");
                    tab.style.width = "400px";
                    tab.style.height = "300px";
                    //创建table头部
                    var hr = tab.insertRow(0);
                    var htd0 = hr.insertCell(0);
                    htd0.innerHTML = "订单编号";
                    var htd1 = hr.insertCell(1);
                    htd1.innerHTML = "订单日期";
                    var htd2 = hr.insertCell(2);
                    htd2.innerHTML = "代理商";
                    var htd3 = hr.insertCell(3);
                    htd3.innerHTML = "金额";
                    //填充table内容
                    for (var i = 0; i < data.length; i++) {
                        var row = tab.insertRow(i + 1);
                        var td0 = row.insertCell(0);
                        td0.innerHTML = data[i].OrderID;
                        var td1 = row.insertCell(1);
                        td1.innerHTML = data[i].OrderTime;
                        var td2 = row.insertCell(2);
                        td2.innerHTML = data[i].Proxy;
                        var td3 = row.insertCell(3);
                        td3.innerHTML = data[i].Amount;
                    }
                    document.getElementById("divTest").appendChild(tab);
                }, function(e) {
                    alert("Ajax错误:" + e.Message);
                });
            }
        </script>
    
    </head>
    <body>
        <form id="form1" runat="server">
        <div id="divTest">
            <input type="button" id="btnTest" value="Ajax获取服务器数据" onclick="GetOrders();" />
        </div>
        </form>
    </body>
    </html>
    
    

      页面效果图一:

     

      页面效果图二:

     

    不足之处,请指正。旨在学习。

    懒惰,是一个通病。 努力,必会成为一种习惯。
  • 相关阅读:
    手把手教你做关键词匹配项目(搜索引擎)---- 第十八天
    数据库那点事儿
    手把手教你做关键词匹配项目(搜索引擎)---- 第十七天
    手把手教你做关键词匹配项目(搜索引擎)---- 第十六天
    屌丝的坑人表单神器
    手把手教你做关键词匹配项目(搜索引擎)---- 第十五天
    手把手教你做关键词匹配项目(搜索引擎)---- 第十四天
    手把手教你做关键词匹配项目(搜索引擎)---- 第十三天
    手把手教你做关键词匹配项目(搜索引擎)---- 第十二天
    手把手教你做关键词匹配项目(搜索引擎)---- 第十一天
  • 原文地址:https://www.cnblogs.com/encoding/p/1846506.html
Copyright © 2011-2022 走看看