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<string, object> Request; /// <summary> /// 用户id /// </summary> public string UserID { get; set; } public RefRequestEntity() { PageRights = new List<RightEntity>(); Request = new HuberRequest<string, object>(); } }
在.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, null, null, 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, null, null, 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, null, null, 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, null, null, 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, null, null, 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 { get; set; } /// <summary>返回结果的内容 /// 如果是ResultType=_Redirect那么ResultContext=301 /// 如果是ResultType=_Stream那么ResultContext="文件名.zip",当然这个文件名可以随意定义 /// </summary> public object ResultContext { get; set; } /// <summary>返回结果的文件流 /// </summary> public byte[] ResultStream { get; set; } } |
|
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
net搭建热插拔式web框架的更多相关文章
- 第三篇 基于.net搭建热插拔式web框架(重造Controller)
由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个contro ...
- 第二篇 基于.net搭建热插拔式web框架(沙箱的构建)
上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章很多人看了以后,都表示不解,觉得不知道我到底 ...
- 基于.net搭建热插拔式web框架(实现原理)
第一节:我们为什么需要一个热插拔式的web框架? 模块之间独立开发 假设我们要做一个后台管理系统,其中包括“用户活跃度”.“产品管理”."账单管理"等模块.每个模块中有自己的业务特 ...
- net搭建热插拔式web框架(沙箱的构建)
net搭建热插拔式web框架(沙箱的构建) 上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章 ...
- 第五篇 基于.net搭建热插拔式web框架(拦截器---请求管道)
好了,前边我们把核心内容介绍完了,接下来要做的就是拦截用户的请求,并把请求转向沙箱内. 这里我们准备通过实现一个HttpModule类来完成请求的拦截与转发.新建一个HuberHttpModule类, ...
- 第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)
在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持. 回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图 ...
- 架构探险——第三章(搭建轻量级Java Web框架)
解决的问题 servlet的数量会随业务功能的扩展而不断增加,我们有必要减少servlet的数量,交给controller处理,它负责调用service的相关方法,并将返回值放入request或res ...
- 读《架构探险——从零开始写Java Web框架》
内容提要 <架构探险--从零开始写Java Web框架>首先从一个简单的 Web 应用开始,让读者学会如何使用 IDEA.Maven.Git 等开发工具搭建 Java Web 应用:接着通 ...
- 【原】Go语言及Web框架Beego环境无脑搭建
本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...
随机推荐
- 201215-03-19---cocos2dx内存管理--具体解释
因为cocos2dx我们的使用c++写的,所以内存管理就是一个绕只是去的坎,这个你不懂内存仅仅懂业务逻辑的话,还玩什么c++,今天看了半天这个东西,事实上本质上是理解的,可是就是有一个过不去的坎,最终 ...
- 使用EXCEL设置“下拉菜单”选项功能
原创作品.出自 "深蓝的blog" 博客.欢迎转载.转载时请务必注明出处,否则有权追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...
- DOM的event对象的属性和方法
属性/方法 类型 是否可读写 描写叙述 altKey Boolean 读写 指示是否按下alt键 bubbles Boolean 读 指示事件是否冒泡 button Intrger 读写 鼠标事件发生 ...
- SQL Server 2008备份数据库失败,拒绝访问的原因
原文:SQL Server 2008备份数据库失败,拒绝访问的原因 备份数据到特定目录是出现拒绝访问,然后测试备份到C盘根目录正常. 查了下原因: 是因为那个目录没有Authenticated Use ...
- Redis集群明细文档(转)
相信很多用过Redis的同学都知道,Redis目前版本是没有提供集群功能的,只能单打独斗.如果要实现多台Redis同时提供服务只能通过客户端自身去实现.目前根据文档已经看到Redis正在开发集群功能, ...
- (转)在 Visual Studio 2010 中创建 ASP.Net Web Service
很多人在论坛里说,在Visual Studio 2010中不能创建“ASP.Net Web Service”这种project了,下面跟帖者云云,有的说这是因为微软已经将Web Service整合进W ...
- Redshift扩容及踩到的坑
下午发现redshift集群已经没有什么空间了.删掉一些不须要的暂时表也仅仅降到86%左右,为了能放下这两天的数据必须扩容了 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...
- UVA 11324 - The Largest Clique(强连通分量+缩点)
UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内随意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分 ...
- cocos2d-x 2.2.3 创建项目的方法
直接复制粘贴到txt文本,然后修改后缀为.bat,然后将bat文件放到tools\project-creator的目录下即可. :project_input @echo 请输入项目名称,按回车,例:H ...
- Wake-On-LAN待机或休眠模式中唤醒
Wake-On-LAN简称WOL,是一种电源管理功能:如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒.许多主板厂商支持IBM提出的网络唤醒标准.该标准允许网络管理员远程打开PC机电源,以 ...