zoukankan      html  css  js  c++  java
  • 重写IHttpHandler,实现前后端分离

    再说重写IHttpHandler,实现前后端分离

     

    aspx页面第一次加载时,HttpHandler 里面是如何编译指定页面的呢?Framework提供了编译页面的API如下:

    BuildManager.CreateInstanceFromVirtualPath(url, typeof(System.Web.UI.Page));根据虚拟路径生成实例。

    但是url页面此时必需继承System.Web.UI.Page,就是我们常见的ASPX页面。但是这样编译时会调用aspx视图引擎来解析aspx和对应的CodeBehind类。

    对于前台纯粹用JSON渲染的JS插件,解析编译ASPX页面似乎是多余的,aspx的生命周期也是复杂和没什么卵用的,那问题来了,能不能只编译类文件(当然要继承IHttpHandler),而aspx页面用html替换呢?

    如下图的结构,(如何一键建立这样的文件结构下次再说,MVC中View和Controller分的太开了,不太习惯,中小型项目还是这样觉的更好。)

    目标:html上发送ajax请求到.cs上,并返回数据到.html

    Framework提供一个方法:

    var ass = BuildManager.GetCompiledAssembly(url);根据虚拟路径得到程序集。第一次加载需要编译慢一点,之后会很快。

    url可以是这样:/Portal/ListPageTmp.cs,即根据class文件路径生成Assembly,

    当然此时浏览器url是/Portal/ListPageTmp.html

    我们可以在前台ajax请求时就把路径由/Portal/ListPageTmp.html转换成/Portal/ListPageTmp.cs,再发送ajax,也可以在后台GetHandler方法里面转换。

    我是在前台转换的如下:(把$.ajax封装一下,确保所有AJAX都调用此方法以便转换url)

    $.ajax({
    type: 'post',
    url: ‘/Portal/ListPageTmp.cs’,
    async: async,
    data: data,
    success: function (data) { rtn = data; },
    error: function (data) { rtn["result"] = "fail"; alert("操作失败") },
    dataType: 'json'
    });

    要想以这样ajax请求(/Portal/ListPageTmp.cs)让IIS接收到 那必然要改web.Config:不解释

    <system.webServer>
    <handlers>
    <add name="ddd" verb="*" path="*.cs" type="App.PageBase.CSHttpHandler" />
    </handlers>
    </system.webServer>

    以下是IHttpHandlerFactory完整代码:

    复制代码
     1  public class CSHttpHandler : IHttpHandlerFactory
     2     {
     3         public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
     4         {
     5 
     6             try
     7             {
     8                 var ass = BuildManager.GetCompiledAssembly(url);//重要的一个方法,也见过其它的跟据url生成实例的方法,但是如果不同命名空间有同名类就不好办了。
     9                // var d = BuildManager.CreateInstanceFromVirtualPath(url, typeof(System.Web.UI.Page));
    10               
    11                 TypeInfo pageType = ass.DefinedTypes.Where(p => p.IsClass == true && p.BaseType.BaseType == typeof(BasePage)).FirstOrDefault();
    12                 BasePage basepage = Activator.CreateInstance(pageType) as BasePage;
    13                 return (IHttpHandler)basepage;
    14             }
    15             catch (Exception ex)
    16             {
    17                 throw ex;
    18             }
    19 
    20         }
    21 
    22         public void ReleaseHandler(IHttpHandler handler)
    23         {
    24 
    25 
    26         }
    27 
    28     }
    复制代码
    BasePage类,和System.Web.UI.Page类功能相当。
    复制代码
      1     public class BasePage : IHttpHandler
      2     {
      3 
      4      private bool _IsAjaxRequest;
      7         private string _Action;
      8         private ActionResult _ActionResult;
      9         AppCache cache = new AppCache();
     10         public BasePage()
     11         {
     12             this.IsCheckLogin = true;
     13 
     14             this.IsCheckAuth = true;
     15 
     16             _ActionResult = new ActionResult();
     17 
     18 
     19 
     20         }
     21 
     22         public bool IsReusable { get; set; }
     23         protected HttpRequest Request
     24         {
     25             get;
     26             set;
     27         }
     28         protected HttpResponse Response
     29         {
     30             get;
     31             set;
     32         }
     33 
     34         public virtual void ProcessRequest(HttpContext context)
     35         {
     36             this.Request = context.Request;
     37             this.Response = context.Response;
     38             this.OnInit();
     39 
     40         }
     41         protected string Action
     42         {
     43             get
     44             {
     45                 return _Action;
     46             }
     47 
     48 
     49         }
    //判断是否AJAX请求,这种模式,到这里的请求都是AJAX请求,因为HTML加载时不用触发请求到后端的。 50 protected bool IsAjaxRequest 51 { 52 get 53 { 54 return _IsAjaxRequest; 55 } 56 57 58 } 59 protected virtual void OnInit() 60 { 61 _IsAjaxRequest = this.Request.Headers["X-Requested-With"] == "XMLHttpRequest" ? true : false; 62 _Action = Request.QueryString["Action"] == null ? "" : Request.QueryString["Action"].ToString(); 63 form = new FormData(Request.Form);
    //根据URL上的Action参数找到继承此类上的方法,并反射调用。

    MethodInfo method = this.GetType().GetMethod(Action);
    if (method == null)
    {
    throw new Exception("找不到【" + method.Name + "】方法.");
    }
    else
    {
    try
    {

    //绑定参数并调用,当然调用前也可以也可以做ActionFilter检查
    InvokMethod(this, method);

    
    

    }
    catch (Exception ex)
    {
     actionResut.hasError = true;
     actionResut.message = ex.InnerException.Message;
    }

    
    

    }

    //返回json数据
    ReturnData(actionResut);


    64 }
    //绑定Action方法的参数。 65 protected object InvokMethod(object ins, MethodInfo method) 66 { 67 68 69 var methodParam = method.GetParameters(); 70 object[] param = new object[methodParam.Length]; 71 for (int i = 0; i < methodParam.Length; i++) 72 { 73 string name = methodParam[i].Name; 74 Type paramType = methodParam[i].ParameterType; 75 if (paramType.IsGenericType) paramType = paramType.GetGenericArguments()[0]; 76 string ArgValue = Request.QueryString[name]; 77 string FormValue = Request.Form[name]; 78 string value = string.IsNullOrEmpty(ArgValue) ? FormValue : ArgValue; 79 if (!string.IsNullOrEmpty(value)) 80 { 81 if (paramType.IsValueType) 82 { 83 param[i] = Convert.ChangeType(value, paramType); 84 } 85 else if (paramType == typeof(string)) 86 { 87 param[i] = value; 88 } 89 else 90 { 91 param[i] = JsonHelper.Json2Object(value.ToString(), paramType); 92 } 93 } 94 95 else 96 { 97 param[i] = null; 98 } 99 } 100 return method.Invoke(ins, param); 101 102 } 103 }
    复制代码
    ListPageTmp.html对应的类文件是这样的:
    如果有ListPageTmp.html?Action=Test&Id=1&name=zhangsan的ajax请求,会根据名称找到ListPageTmp.cs,实例化后将url参数绑定到Test方法参数上执行,返回JSON.
     
    复制代码
     1     public partial class ListPageTmp :BasePage
     2     { 
     3     
    [Auth(Role="Admin")]//反射调用前也可检查是否有attribute并做 拦截 ,类似MVC的ActionFilter. 4 public void Test(int Id,string name) 5 { 6 7 actionResut.Add("Name",name);
                   actionResut.Add("Id",Id);
     8            
     9         }
    10 
    11   
    12     
    13     }
    复制代码

    这样前后端就分开了。html加载完成后,根据不同需要发送ajax从服务端取json数据绑定的前台。

    也实现了MVC里面的一些功能,如ActionFilter,Action参数绑定,ActionResult和MVC的不太一样。没有很复杂的ActionResult,只是封装json.

    MVC是通过URL 路由 找到 Control和Action,由Action定向到View,

    今天说的这个方案,是通过View找到Control和Action 执行后返回JSON给View.

    唉,不知道说明白了没有。。。。

     
    分类: .NET
  • 相关阅读:
    初识Qt基于http协议网页浏览
    初识Qt涂鸦板绘制
    初识Qt图片显示、平移及旋转
    初识Qt文字绘制
    初识Qt鼠标、键盘事件及定时器和随机数
    初识Qt窗口界面
    初识Qt布局管理器
    解决VC++6.0打开文件或添加文件到工程出错的问题
    asp.net动态添加GridView的模板列,并获取列值
    asp.net中下载文件的问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4746539.html
Copyright © 2011-2022 走看看