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: ...
随机推荐
- Computational Network Toolkit (CNTK) 是微软出品的开源深度学习工具包
Computational Network Toolkit (CNTK) 是微软出品的开源深度学习工具包 用 CNTK 搞深度学习 (一) 入门 Computational Network Toolk ...
- RCP开发中错误:java.lang.RuntimeException: WARNING: Prevented recursive attempt to activate part...
在做RCP的eclipse插件开发时,启动管理软件界面时,总是报如下错误 : !ENTRY org.eclipse.ui.workbench 4 0 2012-05-25 18:44:21.306 ! ...
- [Unity3D]Unity3D游戏开发之ACT游戏三连击效果实现综述
各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.在研究了Unity3D Mecanim动画系统的重定向特性后,今天我们继续来探索Me ...
- Redis启动多端口,运行多实例(转)
使用redis在同一台机器上,启用多个端口,实现多个实例,完成集群的模拟实现. 启动多实例 redis默认启动端口为6379,我们可以使用 --port 来指定多个端口,如下,在linux终端命令: ...
- JarSearch
个人做的小工具分享给大家~~. 支持从压缩文件搜索文件,特别是根据部分类文件名在jar里查找文件,比较方便,效率也还不错. 也支持从目录查找 http://pan.baidu.com/s/1feYaM ...
- OpenCL 查看设备信息
好久没搞OpenCL了.可是这是个好东西.不能不学,之前发了篇设置OpenCL的文章.看的人还真多,看来大家都知道这个好东西了,都想把OpenCL搞起.只是学习难度还是相当高的. 之前忙搞算法,所以非 ...
- CSDN开源夏令营 百度数据可视化实践 ECharts(8)问题分析
ECharts问题描写叙述: 问题就是折线图上的点是显示的,有人问能不能一開始不显示,当你点击的时候或者是当鼠标移动到上面的时候,折线上的点才显示? 例如以下图所看到的: 分析:让折线上的点不显示能够 ...
- SWT中各种参数大全
1按钮组件(Button) (1)Button组件常用样式 SWT.PUSH按钮 SWT.CHECK多选按钮 SWT.RADIO单选按钮 SWT.ARROW箭头按钮 SWT.NONE默认按钮 SWT. ...
- vb.net WPF webbrowser window.close 关闭后不触发 WindowClosing 事件 WNDPROC解决方式
vb.net WPF webbrowser window.close 关闭后不触发 WindowClosing 事件 WNDPROC解决方式 #Region "WPF 当浏览器窗体关闭 ...
- pygame系列_mouse鼠标事件
pygame.mouse提供了一些方法获取鼠标设备当前的状态 ''' pygame.mouse.get_pressed - get the state of the mouse buttons get ...