net搭建热插拔式web框架(重造Controller)

由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个controller。

  我们在写mvc项目的时候经常会用到ViewBag、ViewData,那我们就先声明这两个变量:

  

1
2
public dynamic ViewBag = new DynamicViewBag();
public ViewDataDictionary ViewData = new ViewDataDictionary();

  当然还可以根据自己的需要构建更多的特性。

  我们在一个网络请求中避免不了会携带一些参数,那这些参数该如何传到沙箱中呢?我们定义了一个RefRequestEntity类,他负责对我们的参数经行打包,把参数打包后对象作为参数传到沙箱内部:

+ /// <summary>用户的请求信息

    /// </summary>
    [Serializable]
    public class RefRequestEntity
    {
        /// <summary>当前用户在本页面具备的所有权限
        /// </summary>
        public List<RightEntity> PageRights;
        /// <summary>用户请求携带的所有参数
        /// </summary>
        public HuberRequest<stringobject> Request;
        /// <summary>
        /// 用户id
        /// </summary>
        public string UserID { getset; }
        public RefRequestEntity()
        {
            PageRights = new List<RightEntity>();
            Request = new HuberRequest<stringobject>();
        }
    }

  

  在.net mvc中我们可以返回ActionResult,在ActionResult内部调用时才会做出真正的Response(更多细节请参考mvc实现原理),当然它在执行的整个过程中都是由HttpContext贯穿的,我们没有了HttpContext,我们就只自己构造一些Response方法。

  返回View()结果:

  mvc中由ViewEngine来编译执行我们写好的视图文件(.aspx、.cshtml),而我们则借助于RazorEngine来编译执行razor视图文件,它可以支持我们常用的ViewBag、using、layout等(更多请见RazorEngine)。在本篇中我们还是把精力放回controller的实现中,关于视图的实现我们在下一篇中在讲。我们先看一下一个View的简单实现:

1
2
3
4
5
6
7
8
9
10
/// <summary>返回试图的执行结果
        /// </summary>
        /// <returns></returns>
        protected string View()
        {
            var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Global);//getActionPath:获取action对应的视图文件key值。
 
 
       return new CompileView().RunCompile(tKey, nullnull, ViewBag); //返回执行结果
     }

  View()的执行结果是一段html代码。这样我们在请求一个action的时候,就可以正常的呈现一个页面了。下边是一个Controller基类的实现,它完成了View、PartialView的实现Demo:

+ public class HuberController

    {
 
        public dynamic ViewBag = new DynamicViewBag();
        public ViewDataDictionary ViewData = new ViewDataDictionary();
 
        
        /// <summary>设置ViewBag的值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        internal void AddViewBageValues(string key, object value)
        {
 
            Impromptu.InvokeSet(ViewBag, key, value);
 
        }
 
        /// <summary>返回试图的执行结果
        /// </summary>
        /// <returns></returns>
        protected string View()
        {
            var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Global);
            return new CompileView().RunCompile(tKey, nullnull, ViewBag);
        }
        /// <summary>返回试图的执行结果
        /// </summary>
        /// <typeparam name="T">model的类型</typeparam>
        /// <param name="model">model</param>
        /// <returns></returns>
        protected string View<T>(T model)
        {
            var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Global);
            return new CompileView().RunCompile(tKey, typeof(T), model, ViewBag);
        }
        /// <summary>返回试图的执行结果
        /// </summary>
        /// <param name="viewName">视图的全路径(相对于运行目录的全路径)</param>
        /// <returns></returns>
        protected string View(string viewName)
        {
            var tKey = Engine.Razor.GetKey(getActionPathWith(viewName), ResolveType.Global);
            return new CompileView().RunCompile(tKey, nullnull, ViewBag);
        }
        /// <summary>返回试图的执行结果
        /// </summary>
        /// <typeparam name="T">model的类型</typeparam>
        /// <param name="viewName">视图的全路径(相对于运行目录的全路径)</param>
        /// <param name="model">model</param>
        /// <returns></returns>
        protected string View<T>(string viewName, T model)
        {
            var tKey = Engine.Razor.GetKey(getActionPathWith(viewName), ResolveType.Global);
            return new CompileView().RunCompile(tKey, typeof(T), model, ViewBag);
        }
 
        /// <summary>返回局部试图的执行结果
        /// </summary>
        /// <returns></returns>
        protected string PartialView()
        {
            var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Include);
            return new CompileView().RunCompile(tKey, nullnull, ViewBag);
        }
        /// <summary>返回局部试图的执行结果
        /// </summary>
        /// <typeparam name="T">model的类型</typeparam>
        /// <param name="model">model</param>
        /// <returns></returns>
        protected string PartialView<T>(T model)
        {
            var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Include);
            return new CompileView().RunCompile(tKey, typeof(T), model, ViewBag);
        }
        /// <summary>返回局部试图的执行结果
        /// </summary>
        /// <param name="viewName">视图的全路径(相对于运行目录的全路径)</param>
        /// <returns></returns>
        protected string PartialView(string viewName)
        {
            var tKey = Engine.Razor.GetKey(getActionPathWith(viewName), ResolveType.Include);
            return new CompileView().RunCompile(tKey, nullnull, ViewBag);
        }
        /// <summary>返回局部试图的执行结果
        /// </summary>
        /// <typeparam name="T">model的类型</typeparam>
        /// <param name="viewName">视图的全路径(相对于运行目录的全路径)</param>
        /// <param name="model">model</param>
        /// <returns></returns>
        protected string PartialView<T>(string viewName, T model)
        {
            var tKey = Engine.Razor.GetKey(getActionPathWith(viewName), ResolveType.Include);
            return new CompileView().RunCompile(tKey, typeof(T), model, ViewBag);
        }
 
 
 
        /// <summary>获取action对应view的物理文件地址
        /// </summary>
        /// <returns></returns>
        private string getActionPath()
        {
            string key = string.Empty;
            StackTrace trace = new StackTrace();
            MethodBase methodName = trace.GetFrame(2).GetMethod();
            string className = methodName.ReflectedType.FullName;
 
            string assName = HuberHttpModule.CurDomainAssemblyName;
            key = className.Substring(assName.Length);
            key = key.Replace(".Controllers."".Views.");
            key = key.Substring(0, key.Length - 10);
            key = key.Replace(".""\\");
            key += "\\" + methodName.Name + ".cshtml";
            return key;
        }
        /// <summary>根据action名获取其对应view的物理文件地址
        /// </summary>
        /// <param name="ActionName">action名(同一controller中)</param>
        /// <returns></returns>
        private string getActionPathWith(string ActionName)
        {
            string key = string.Empty;
            StackTrace trace = new StackTrace();
            MethodBase methodName = trace.GetFrame(2).GetMethod();
            string className = methodName.ReflectedType.FullName;
 
            string assName = HuberHttpModule.CurDomainAssemblyName;
            key = className.Substring(assName.Length);
            key = key.Replace(".Controllers."".Views.");
            key = key.Substring(0, key.Length - 10);
            key = key.Replace(".""\\");
            key += "\\" + ActionName + ".cshtml";
            return key;
        }
    }

   我们上边列出了对Razor编译执行的简单过程,还是那句话,RazorEngine的更多实现细节将在下一篇讲解。那么现在问题来了,我们得到了html代码或者说我们执行玩自己的业务逻辑以后如何把这个结果输出呢(即HttpResponse)?

  我们定义了一个RefRespondEntity类,它来承载返回结果,并把结果返回到沙箱外层的调用者,再由这个调用者将这个RefRespondEntity对象Response出去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Serializable]
  public class RefRespondEntity
  {
      public RefRespondEntity(RespondType type)
      {
          ResultType = type;
      }
      /// <summary>返回结果的数据类型
      /// </summary>
      public RespondType ResultType { getset; }
      /// <summary>返回结果的内容
      /// 如果是ResultType=_Redirect那么ResultContext=301
      /// 如果是ResultType=_Stream那么ResultContext="文件名.zip",当然这个文件名可以随意定义
      /// </summary>
      public object ResultContext { getset; }
      /// <summary>返回结果的文件流
      /// </summary>
      public byte[] ResultStream { getset; }
  }

  

1
2
3
4
5
6
7
8
9
10
11
12
13
//一个action的demo      
public RefRespondEntity Index4(RefRequestEntity param)
{
 
     object AA = param.Request["A"];
     object BB = param.Request["B"];
     object CC = param.Request["C"];
 
    RefRespondEntity result = new RefRespondEntity(RespondType._String);
    result.ResultContext = View();
    object tt =   ViewBag.test;
    return result;
}

  

 

1
var result = sandBox.InvokeMothod(urlEntity.controller, urlEntity.action, paras);//sandBox是一个沙箱的实例化对象
1
RequestHandle.ResposeResult(respond, result);//输出结果

  

+ /// <summary>响应工具类

    /// </summary>
    public class RequestHandle
    {
        private static bool IsAjax(HttpRequest request)
        {
            return request.Headers["X-Requested-With"] != null;
        }
 
        /// <summary>将reques请求的参数封装到CorRefEntity对象中
        /// </summary>
        /// <param name="para"></param>
        /// <param name="request"></param>
        public static void FillCorRefEntity(RefRequestEntity para, HttpRequest request)
        {
            foreach (var key in request.Params.AllKeys)
            {
                para.Request.Add(key, request.Params[key]);
 
            }
        }
        /// <summary>URL404
        /// </summary>
        /// <param name="request"></param>
        /// <param name="respond"></param>
        public static void ResponseNotfound(HttpRequest request, HttpResponse respond)
        {
            if (IsAjax(request))
            {
                respond.Write(ResponseCodeEntity.CODE404);
                respond.End();
            }
            else
            {
                respond.Redirect(ResponseCodeEntity.ULR404);
                respond.End();
            }
        }
        /// <summary>NoLogin
        /// </summary>
        /// <param name="request"></param>
        /// <param name="respond"></param>
        public static void ResponseNoLogin(HttpRequest request, HttpResponse respond)
        {
            if (IsAjax(request))
            {
                respond.Write(ResponseCodeEntity.NoLogin);
                respond.End();
            }
            else
            {
                respond.Redirect(ResponseCodeEntity.LoginURL);//需要改成非调转形式
                respond.End();
            }
        }
        /// <summary>NoRight
        /// </summary>
        /// <param name="request"></param>
        /// <param name="respond"></param>
        public static void ResponseNoRight(HttpRequest request, HttpResponse respond)
        {
            if (IsAjax(request))
            {
                respond.Write(ResponseCodeEntity.NoRight);
                respond.End();
            }
            else
            {
                respond.Redirect(ResponseCodeEntity.NoRightURL);//需要改成非调转形式
                respond.End();
            }
        }
 
        public static void ResposeResult(HttpResponse respond, object result)
        {
            if (typeof(RefRespondEntity) == result.GetType())
            {
                RefRespondEntity temp_result = (RefRespondEntity)result;
                if (temp_result.ResultType == RespondType._Redirect)
                {
                    respond.Redirect((string)temp_result.ResultContext);
                    respond.End();
                }
                else if (temp_result.ResultType == RespondType._Stream)
                {
                    byte[] st = (byte[])temp_result.ResultStream;
                    respond.ContentType = "application/octet-stream";
                    respond.AddHeader("Content-Disposition"string.Format("attachment; filename={0}", (string)temp_result.ResultContext));
                    respond.OutputStream.Write(st, 0, st.Length);
                    respond.End();
                }
                else
                {
                    respond.Write(temp_result.ResultContext);
                    respond.End();
                }
            }
            else
            {
                respond.Write("Huber Module respose is not a RefRespondEntity");
            }
        }
    }

  

+ public class ResponseCodeEntity

 {
     /// <summary>404
     /// </summary>
     public static string ULR404 = "/NotPageFound/_404";
     /// <summary>404ajax
     /// </summary>
     public static string CODE404 = "NotPage";
     /// <summary>登录页URL
     /// </summary>
     public static string LoginURL = "/User/Login";
     /// <summary>未登录ajax
     /// </summary>
     public static string NoLogin = "NoLogin";
     /// <summary>没有权限ajax
     /// </summary>
     public static string NoRight = "NoRight";
     /// <summary>没有权限url
     /// </summary>
     public static string NoRightURL = "/User/NoRight";
 }

  

转载请注明出处:http://www.cnblogs.com/eric-z/p/5028243.html
 
分类: asp.netasp.net mvc

net搭建热插拔式web框架的更多相关文章

  1. 第三篇 基于.net搭建热插拔式web框架(重造Controller)

    由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个contro ...

  2. 第二篇 基于.net搭建热插拔式web框架(沙箱的构建)

    上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章很多人看了以后,都表示不解,觉得不知道我到底 ...

  3. 基于.net搭建热插拔式web框架(实现原理)

    第一节:我们为什么需要一个热插拔式的web框架? 模块之间独立开发 假设我们要做一个后台管理系统,其中包括“用户活跃度”.“产品管理”."账单管理"等模块.每个模块中有自己的业务特 ...

  4. net搭建热插拔式web框架(沙箱的构建)

    net搭建热插拔式web框架(沙箱的构建) 上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章 ...

  5. 第五篇 基于.net搭建热插拔式web框架(拦截器---请求管道)

    好了,前边我们把核心内容介绍完了,接下来要做的就是拦截用户的请求,并把请求转向沙箱内. 这里我们准备通过实现一个HttpModule类来完成请求的拦截与转发.新建一个HuberHttpModule类, ...

  6. 第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)

    在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持. 回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图 ...

  7. 架构探险——第三章(搭建轻量级Java Web框架)

    解决的问题 servlet的数量会随业务功能的扩展而不断增加,我们有必要减少servlet的数量,交给controller处理,它负责调用service的相关方法,并将返回值放入request或res ...

  8. 读《架构探险——从零开始写Java Web框架》

    内容提要 <架构探险--从零开始写Java Web框架>首先从一个简单的 Web 应用开始,让读者学会如何使用 IDEA.Maven.Git 等开发工具搭建 Java Web 应用:接着通 ...

  9. 【原】Go语言及Web框架Beego环境无脑搭建

    本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...

随机推荐

  1. 杭电acm阶段之理工大版

    想參加全国软件设计大赛C/C++语言组的同学,假设前一篇<C和指针课后练习题总结>没看完的,请先看完而且依照上面的训练做完,然后做以下的训练. 传送门:http://blog.csdn.n ...

  2. RGB與CIELAB色彩空間轉換

    原地址:http://cg2010studio.wordpress.com/2012/10/02/rgb與cielab色彩空間轉換/ 之前有研究CIE L*a*b*色彩空間,現在想更進一步探討RGB色 ...

  3. 实现ListView A~Z快速索引

    ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...

  4. 【Android小应用】颈椎保健操Android开源项目

    前段时间在知乎上回答已入 IT 行业的前辈,有哪些关于保护身体健康的知识分享给 IT 新人? ,回复了一张图片,评论里面有知友希望通过程序可以实现,我后面尝试着通过程序实现了效果,现开源出来,大家可以 ...

  5. 一张图总结Google C++编程规范(Google C++ Style Guide)

    Google C++ Style Guide是一份不错的C++编码指南,我制作了一张比較全面的说明图,能够在短时间内高速掌握规范的重点内容.只是规范毕竟是人定的,记得活学活用.看图前别忘了阅读以下三条 ...

  6. hdu 2642 二维树状数组 单点更新区间查询 模板水题

    Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Subm ...

  7. set echo on/off,set term on/off,set feedback off,set heading off命令(转)

    1.term命令:  当和SPOOL命令联合使用时,可以取消SQLPLUS输出,查询结果仅仅存在于假脱机文件中  set term on:查询结果既显示于假脱机文件中,又在SQLPLUS中显示:  s ...

  8. silverlight游戏在坑内发展

    最初做<金X>使用silverlight它是由于右手锯的深蓝色silverlight游戏开发教程,在这里,好评,写得很好的教程!基于这样的思想游戏覆盖.你可以给游戏开发商新提供的非常多的思 ...

  9. RAC优化大框架的分配(jumbo frame)

    RAC优化大框架的分配(jumbo frame) 首先讲讲MTU的概念:在网络通信中,有个MTU(Max Transmission Unit)的概念,即网络传输中最大帧的大小,这个值默认是1500By ...

  10. nutch搏斗之一

    nutch搏斗之一 问题描述: 在用nutch1.0做generate 包括5亿url的crawldb时,它默认按照64M分块,分成777个map task,在运行的后期出现 Could not fi ...