在ashx中利用反射+jquery轻松处理ajax 含Demo源码
由于jquery的出现,编写js代码已经变得异常的平民化,同时现在的web也已经是ajax满天飞,哪天你自己写一个web不含ajax的拿不出手
当然,在.net的控件模式开发中一种去控件化开发已经变的变得更加通用:jquery+ajax+ashx 这种方式更加适用于一些小应用的开发,轻量、简单、自由
由于那时候太年轻,刚刚开始这种模式开发的时候 是一个ajax请求一个ashx页面,这样的结果可想而知,一个小的权限系统光光ashx文件就几十个了,而且文件名还大同小异,悲剧。
后来做了一会儿变聪明了,把相同类别的请求都放到一个ashx文件中,每个请求传一个请求标志 通过switch来调用相应的请求方法,当然,这样要比原来好多了,至少没那么多ashx文件了,但是 每新建一个文件都要去添加switch方法,蛋疼啊 有木有,更加可耻的是 每次增删改一个请求都要去修改那个可恶的switch语句,烦啊
后来知道了反射,知道可以用反射来动态调用方法,脑子一转,哇 好主意,查了相关资料,没几分钟就把这个框架写了出来,然后百度一搜,次奥,关于这种的都有那么多文章了,本来都不想再写这篇文章,重复造轮子啊 要被骂的有木有,不过想想代码都写了,而且还是自己写的,写篇文章纪念一下,而且这个东西感觉比网上的更加方便,实用,嘿嘿。
下面就是这个handler主心骨鸡类的详解了
首先在这个鸡类中定义几个默认的参数
/// <summary> /// 指定过来的http请求类型 主要指定action方法名称的接收方式 get 或者 post /// </summary> protected NameValueCollection _httpReuqest = HttpContext.Current.Request.Form; /// <summary> /// 指定返回头 /// </summary> protected string _contentType = "text/plain" ; /// <summary> /// 指定接收action方法的参数名称 /// </summary> protected string _actionName = "action" ; |
主要是定义默认的请求方式 GET或者POST 当然默认是POST,相对安全点嘛,并且个人用的也多,当然这个请求方式在子类中可以把它改掉呢
还有就是请求的返回头,方法名称的参数 代码的注释里面都写得很清楚呢
下面就是动态调用方法的核心代码啦(再这里给个反射连接的相关知识,不知道的点我哦)
//根据指定的请求类型获取方法名 string action = this ._httpReuqest[ this ._actionName]; if (! string .IsNullOrEmpty(action)) { //获取方法的实例 非静态 需要Public访问权限 忽略大小写 MethodInfo methodInfo = this .GetType().GetMethod(action, BindingFlags.Instance|BindingFlags.Public|BindingFlags.IgnoreCase); if (methodInfo != null ) { //调用方法 methodInfo.Invoke( this , null ); } else { throw new ApplicationException( string .Format( "没有找到方法{0}" , action)); } } else { throw new ArgumentNullException( "没有找到调用方法参数或者方法名为空" ); } |
核心代码够简单把 其实最核心的就是获取方法实例,当然该方法,两句啦 方便吧
我们看看这个获取方法实例的代码
主要是获取类中的非静态,公开访问,忽略名称大小写的方法,当然你如果不放心 其他的方法也被ajax跨域调用了,你可以给该方法的访问权限设为private或者protected 如果你还是不放心的话 可以喝其他的一样 自定义一个Attribute特征加在方法头上,不过个人在这里感觉没啥必要了
核心的都给你们看了 那来看下鸡类的全部代码吧
/// <summary> /// Handler请求的基类 用此类动态调用请求的方法 /// </summary> public class HandlerBase : IHttpHandler { /// <summary> /// 指定过来的http请求类型 主要指定action方法名称的接收方式 get 或者 post /// </summary> protected NameValueCollection _httpReuqest = HttpContext.Current.Request.Form; /// <summary> /// 指定返回头 /// </summary> protected string _contentType = "text/plain" ; /// <summary> /// 指定接收action方法的参数名称 /// </summary> protected string _actionName = "action" ; //获取当前的http context protected HttpContext Context { get { return HttpContext.Current; } } public void ProcessRequest(HttpContext context) { context.Response.ContentType = this ._contentType; try { //动态调用方法 当然 你还可以在这里加上是否为同域名请求的判断 this .DynamicMethod(); } catch (AmbiguousMatchException amEx) { this .PrintErrorJson( string .Format( "根据该参数{0}找到了多个方法" ,amEx.Message)); } catch (ArgumentException argEx) { this .PrintErrorJson( "参数异常" + argEx.Message); } catch (ApplicationException apEx) { this .PrintErrorJson( "程序异常" + apEx.Message); } } #region 动态调用方法 /// <summary> /// 动态调用方法 /// </summary> private void DynamicMethod() { //根据指定的请求类型获取方法名 string action = this ._httpReuqest[ this ._actionName]; if (! string .IsNullOrEmpty(action)) { //获取方法的实例 非静态 需要Public访问权限 忽略大小写 MethodInfo methodInfo = this .GetType().GetMethod(action, BindingFlags.Instance|BindingFlags.Public|BindingFlags.IgnoreCase); if (methodInfo != null ) { //调用方法 methodInfo.Invoke( this , null ); } else { throw new ApplicationException( string .Format( "没有找到方法{0}" , action)); } } else { throw new ArgumentNullException( "没有找到调用方法参数或者方法名为空" ); } } #endregion #region 打印Json的相关处理 /// <summary> /// 打印遇到异常的json /// </summary> /// <param name="msg"></param> protected void PrintErrorJson( string msg) { this .PrintJson( "error" , msg); } /// <summary> /// 打印成功处理的json /// </summary> /// <param name="msg"></param> protected void PrintSuccessJson( string msg) { this .PrintJson( "success" , msg); } /// <summary> /// 打印json /// </summary> /// <param name="state"></param> /// <param name="msg"></param> protected void PrintJson( string state, string msg) { this .Context.Response.Write( "{\"state\":\"" +state+ "\",\"msg\":\"" + msg + "\"}" ); } #endregion public bool IsReusable { get { return false ; } } } |
够简单把,然后写几个测试ashx页面继承该基类就可以啦
/// <summary> /// Get一般处理程序的测试 /// </summary> public class gethandler : HandlerBase { public gethandler() { //修改请求为get 方式 base ._httpReuqest = base .Context.Request.QueryString; } /// <summary> /// 加法操作 /// </summary> public void Add() { int a = Convert.ToInt32(_httpReuqest[ "a" ]); int b = Convert.ToInt32(_httpReuqest[ "b" ]); PrintSuccessJson((a + b).ToString()); } /// <summary> /// 减法操作 /// </summary> private void Minus() { int a = Convert.ToInt32(_httpReuqest[ "a" ]); int b = Convert.ToInt32(_httpReuqest[ "b" ]); PrintSuccessJson((a - b).ToString()); } } |
下面来个post类型的
/// <summary> /// Post一般处理程序的测试 /// </summary> public class posthandler : HandlerBase { public posthandler() { //修改请求为get 方式 base ._httpReuqest = base .Context.Request.Form; } /// <summary> /// 乘法操作 /// </summary> public void Multiply() { int a = Convert.ToInt32(_httpReuqest[ "a" ]); int b = Convert.ToInt32(_httpReuqest[ "b" ]); PrintSuccessJson((a + b).ToString()); } /// <summary> /// 减法操作 /// </summary> public void Minus() { int a = Convert.ToInt32(_httpReuqest[ "a" ]); int b = Convert.ToInt32(_httpReuqest[ "b" ]); PrintSuccessJson((a - b).ToString()); } } |
很容易看懂吧,前台的html页面就不贴了
如果看的同学实在是看不懂 那赶紧猛击我去下面源码
还有设计不当之处请各位留言指正哦,共同进步哈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库