用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