用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>



  页面效果图一:

 

  页面效果图二:

 用httpHandler实现简易ajax框架

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

你可能感兴趣的:(handler)