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

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

  

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的简单实现:

/// <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出去:

  [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; }
}

  

        //一个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;
}

  

 

var result = sandBox.InvokeMothod(urlEntity.controller, urlEntity.action, paras);//sandBox是一个沙箱的实例化对象
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/5047172.html第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)

第三篇 基于.net搭建热插拔式web框架(重造Controller)的更多相关文章

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

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

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

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

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

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

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

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

  5. net搭建热插拔式web框架

    net搭建热插拔式web框架(重造Controller) 由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并 ...

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

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

  7. 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍

    概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...

  8. 转-基于NodeJS的14款Web框架

    基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...

  9. 2、基于wsgiref模块DIY一个web框架

    一 web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方 ...

随机推荐

  1. Linux之shell篇

    shell是用户与系统交互的界面,这是基本方式之一.标准的shell为bash. shell的操作: 显示所有使用过的命令:history. 执行最近执行过的一条指令:!!.首先会给出执行的是哪一条指 ...

  2. [LeetCode] Arranging Coins 排列硬币

    You have a total of n coins that you want to form in a staircase shape, where every k-th row must ha ...

  3. [LeetCode] Game of Life 生命游戏

    According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...

  4. [LeetCode] Max Points on a Line 共线点个数

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  5. Oracle 表和表数据恢复

    1. 表恢复 对误删的表,只要没有使用 purge 永久删除选项,那么基本上是能从 flashback table 区恢复回来的. 数据表和其中的数据都是可以恢复回来的,记得 flashback ta ...

  6. sql 删除所有表

    sql删除所有表语句: use 数据库名(是要删除表的所在的那个数据库的名称) GO declare @sql varchar(8000) while (select count(*) from sy ...

  7. tensorflow 一些好的blog链接和tensorflow gpu版本安装

    pading :SAME,VALID 区别  http://blog.csdn.net/mao_xiao_feng/article/details/53444333 tensorflow实现的各种算法 ...

  8. C# 通过Selecnuim WebDriver操作非IE浏览器

    之前有需求需要操作Chrome中的dom元素,没做过这个,但是网上关于这个方面的资料比较少,所以自己捣腾了几天,在知道.net中有这个玩意. 但是一百度,全是关于java,python的而c#的那是一 ...

  9. UOJ58 【WC2013】糖果公园

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  10. JavaScript进阶之DOM

    文档对象模型DOM 文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最 ...