由于.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. 编写轻量ajax组件02-AjaxPro浅析

    前言 上一篇介绍了在webform平台实现ajax的一些方式,并且实现一个基类.这一篇我们来看一个开源的组件:ajaxpro.虽然这是一个比较老的组件,不过实现思想和源码还是值得我们学习的.通过上一篇 ...

  2. 使用SharpPCap在C#下进行网络抓包

    在做大学最后的毕业设计了,无线局域网络远程安全监控策略那么抓包是这个系统设计的基础以前一直都是知道用winpcap的,现在网上搜了一下,有用C#封装好了的,很好用下面是其中的几个用法这个类库作者的主页 ...

  3. 《UNIX环境高级编程》笔记——2.标准和实现

    随着UNIX各种衍生版本不断发展壮大,标准化工作就十分必要.其实干啥事都是这样,玩的人多了,必须进行标准化. 一.UNIX标准 1.1 ISO C(ANSI C) ANSI:Amerocan Nato ...

  4. opencv3.0.1 中的SurfFeaturesFinderGpu类的问题.

    最近需要实现一下图像配准的功能, 参考了一下opencv中的实现,发现几个问题, SurfFeaturesFinderGpu在找特征点的过程中会抛出异常,改了一下代码,可以运行了. void Surf ...

  5. wpf 后台比例设置高度

    ColumnDefinition cd0 = new ColumnDefinition(); cd0.Width = new GridLength(2, GridUnitType.Star); txt ...

  6. WebAPI IIS PUT和DELETE请求失败 405

    IIS拒绝PUT和DELETE请求是由于IIS为网站默认注册的一个名为WebDAVModule的自定义HttpModule导致的,如果我们的站点不需要提供针对WebDAV的支持,解决这个问题最为直接的 ...

  7. Django知识点整理

    什么是web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. web应用 访 ...

  8. oracleXE(oracle学习版)在windows的安装配置

    oracleXE其实安装基本就是一路下一步. 在安装前记得先把tomcat打开,不然oracleXE会占用8080端口且安装过程无法更改端口. 如果需要远程连接此oracle XE的话,要关闭这台电脑 ...

  9. 去掉Win7快捷方式小箭头(win10通用)

    我是一个有强迫症的优化控 , 因为近视的缘故 , 喜欢将桌面图标放大 ,  但是win7快捷方式的小箭头 , 确实不好看 . 用win7魔方之类的软件 , 可以解决这个问题 , 但是有时候重启 ,   ...

  10. MySQL索引原理及慢查询优化

    原文:http://tech.meituan.com/mysql-index.html 一个慢查询引发的思考 select count(*) from task where status=2 and ...