用httpHandler实现简易ajax框架
前言:
工作中常常用到以前同事写的一个ajax框架,偶尔抽空看看,感觉恩是复杂,于是自己花心思研究了一个比较简单的,使用httpHandler和反射实现的简易ajax框架。帖出此文,以此铭记,好好学习,天天向上……
步骤一:
首先需要一个接受客户端请求的httpHandler服务,我定义为"AjaxHandler",实现接口"IHttpHandler"和"IRequiresSessionState",有关这两个接口,在此不赘述,有兴趣请翻阅MSDN。
实现一个属性"IsReusable" ,代码如下
1 2 3 4 | public bool IsReusable { get { return false ; } } |
和一个方法"ProcessRequest",用以接受请求。 在这个方法内,我对请求参数头作了如下规定(即Request.Headers):
键 值 含义
InvokeType Ajax 表示请求方式 为 Ajax 请求 目前只支持该请求,有兴趣的朋友可以实现其他的方式
assembly 字符串 表示要请求的服务器方法所在类所在的程序集完全限定名(如:AjaxTest)
space 字符串 表示要请求的服务器方法所在类所在的命名空间(如:Dxy.AjaxTest)
className 字符串 表示要请求的服务器方法所在类的类名称(如:OrderHelper)
methodName 字符串 表示要请求的服务器方法名称(如:GetOrders)
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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." ); } |
整体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 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"
代码如下:
1 2 3 4 | <httpHandlers> <remove verb= "*" path= "*.asmx" /> <add verb= "*" path= "*.dxy" validate= "false" type= "AjaxFramework.AjaxHandler" /> </httpHandlers> |
在这里我规定,凡是后缀为".dxy"的请求都指向"AjaxHandler"时间处理程序。
步骤三:
客户端请求脚本。 ajax核心XMLHttpRequest的创建与请求发送脚本。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | //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对象,然后调用方法传入相应的参数即可。 调用代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <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框架的服务器后台类和页面。
后台测试类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 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); } } } |
页面前台代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <%@ 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> |
页面效果图一:
页面效果图二:
不足之处,请指正。旨在学习。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库