net搭建热插拔式web框架

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

时间: 2024-10-13 16:11:26

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

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

net搭建热插拔式web框架(沙箱的构建) 上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章很多人看了以后,都表示不解,觉得不知道我到底要干什么,可能就像隔行如隔山吧,就像做移动端开发的人很少去考虑分布式中的通信一样.大家都知道模块化,但模块化的思路有很多,我的只是其中一种,也许你看到最后会觉得这种思路在经过不断地演化后会成为一种很好的解决方案,当然这离不开以后大家对代码及思想的贡献. 好

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

好了,前边我们把核心内容介绍完了,接下来要做的就是拦截用户的请求,并把请求转向沙箱内. 这里我们准备通过实现一个HttpModule类来完成请求的拦截与转发.新建一个HuberHttpModule类,并继承IHttpModule.下面我们暂时只处理Application_BeginRequest事件. 先获取request和response对象 HttpApplication application = sender as HttpApplication; HttpResponse respon

基于ASP.Net的热插拨Web框架——理论篇

园子里已经有网友谈论过基于.Net的热插拨Web框架实现,我的方法与之不同.这里记录下来,有兴趣的网友可以看看. 一 设计该框架的缘由和难处 设计这个框架的原因是我想要构建一个类似wordpresss这种能够方便启用.禁用插件和主题的Web应用.Wordpress是一个广受欢迎的博客应用.通过使用wordpress,一个新手也能够快速的搭建一个博客或者网站,用上各种各样的自己需要的插件——从seo.社交媒体账号登陆到后台管理应用插件,再配上好看的主题,只需要几个步骤,你就能够拥有一个时尚并且紧跟

搭建轻量级Jave Web框架----------框架说明

? 版权声明:本文为博主原创文章,转载请注明出处 说明: 本人一年前突然对框架感兴趣,因此买了黄勇老师的<架构探险-从零开始写Java Web框架>一书.书中的讲解.代码都特别详细. 照着书完整实现了smart4j框架.但是因为是跟着老师的思路走的,没有自己的思想,只是"知其然,不知其所以然". 因此打算参照书中的内容写一个自己的简易框架,以此加深理解. 框架内容: 1. Java Web框架 2. 主要使用注解实现 3. 实现依赖注入功能(IOC) 4. 实现控制反转(D

搭建轻量级Jave Web框架----------读取配置文件

? 版权声明:本文为博主原创文章,转载请注明出处 目录: 1.搭建轻量级Jave Web框架----------框架说明 2.搭建轻量级Java Web框架----------读取配置文件 说明: 搭建框架的第一步就是配置文件的读取,这里使用jdk自带的Properties类读取配置文件. 为了准确获取配置文件中的各个键值对的信息,还需要一个工具类进行强制类型转换. 读取过程中还需要进行一些非空的校验等,因此还需要一个工具类对String的一些常用操作进行封装. 总结一下,需要四个java类完成

第3章 搭建轻量级java web框架

MVC这种常用的设计模式可以将应用程序解耦. 若用Servlet来充当C,会产生大量的Servlet.作为一个轻量级框架,我们的目标减少Servlet的数量,对某一业务主题使用统一的Controller,依赖注入Service,结果放入Request或者Response. 本章目标是打造如下的Controller代码: /** * 处理客户管理的相关请求 */ @Controller public class CustomerController { @Inject private Custom

从零开始搭建论坛(一):Web服务器与Web框架

之前用 Django 做过一个小的站点,感觉Django太过笨重,于是就准备换一个比较轻量级的 Web 框架来玩玩.Web.py 作者已经挂掉,项目好久没有更新,所以不准备用它.而 Flask 也是一个成熟的轻量级 Web 框架,在 github 上有众多的 Star 和 Fork,文档和扩展也很丰富,值得学习. 学习一个框架最好的方式就是用框架做一个项目,在实战中理解掌握框架.这里我用 Flask 框架,使用 Mysql 数据库做了一个论坛系统.麻雀虽小,五脏俱全,论坛效果图如下: 下面是论坛

[angularjs] MVC + Web API + AngularJs 搭建简单的 CURD 框架

MVC + Web API + AngularJs 搭建简单的 CURD 框架 GitHub 地址:https://github.com/liqingwen2015/Wen.MvcSinglePage 布局页的引用 <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/bootstrap.min.js"></script&g

Go语言及Web框架Beego环境搭建手顺

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