[ASP.NET]分析MVC5源码,并实现一个ASP.MVC
来源:互联网 发布:淘宝一箩筐 编辑:程序博客网 时间:2024/05/16 01:51
本节内容不是MVC入门教程,主要讲MVC原理,实现一个和ASP.NET MVC类似基本原理的项目.
MVC原理是依赖于ASP.NET管道事件基础之上的.对于这块,可阅读上节内容
[ASP.NET]谈谈IIS与ASP.NET管道
本节目录:
- MVC简介
- MVC5源码
- 实现一个MVC
MVC简介
随着技术的发展,现在已经将MVC模式等同于三层模式。
如果要严格区分的话,UI层指View和Controller,BLL,DAL层和模型层都属于Model中。
在建立MVC项目的时候,选择空的项目,会建立一个如下的项目结构
由于MVC具有以下优点
- 性能高,不需要经过复杂的控件生命周期
- SEO,页面干净,没有ViewState,url地址没后缀名
- 扩展多,ActionResult各种子类,轻松返回JSON,string
- Razor视图引擎
- ....
所以MVC不得不成为ASP.NET的首选开发
扩展
Action的本质就是方法,只要是public的方法,外部都能访问到
MVC原理
路由系统
类图
代码图
路由对象
路由系统
RouteTable
路由表,有个RouteDictionary属性,存放RouteBase的实现类Route。通过Route能返回RouteData.
RouteData中包括
路由系统原理
首先添加一条路由对象,路由对象相当于定制一个url模板
然后创建一个Controller工厂,用来反射调用Controller方法,并缓存所有Controller Type,将其赋值给ControllerBuilder,这个是一个单例对象.
UrlRoutingModule
注册第7个事件,并且根据HttpContext(实际就是读取URL),从RouteTable中获取到RouteData,
然后通过RouteData获取IHttpHandler
扩展:
路由系统依赖UrlRoutingModule,而这个在默认配置的Web.config中已经配置,所以路由并不是ASP.Net MVC专属,而是Asp.Net必经之路.
ActionResult
我们的Action实际上就是返回一个ActionResult.
实际上ActionResult是HttpHandle中PR方法最终输出也是最核心的方法.
这里看下ActionResult源码和JsonResult源码
public
abstract
class
ActionResult
{
public
abstract
void
ExecuteResult(ControllerContext context);
}
public
class
JsonResult : ActionResult
{
public
object
Data {
get
;
set
; }
public
JsonRequestBehavior JsonRequestBehavior {
get
;
set
; }
public
JsonResult()
{
this
.JsonRequestBehavior = JsonRequestBehavior.DenyGet;
}
public
override
void
ExecuteResult(ControllerContext context)
{
JavaScriptSerializer scriptSerializer =
new
JavaScriptSerializer();
if
(
this
.MaxJsonLength.HasValue)
scriptSerializer.MaxJsonLength =
this
.MaxJsonLength.Value;
if
(
this
.RecursionLimit.HasValue)
scriptSerializer.RecursionLimit =
this
.RecursionLimit.Value;
response.Write(scriptSerializer.Serialize(
this
.Data));
}
}
MVC请求流程
- 到达URLModule的第7个Application事件
- 首先根据URL,找到并创建MVCHandle(继承IHttpHandle),
- 映射IHttpHandlehttpContext.RemapHandler(handler)
- 在第11个Application事件后,执行MVCHandle的PR方法
- 根据URL,创建指定Controller(继承Controller,ControllerBase,IController),调用IController的Execute的方法.
- 在ControllerBase的Execute方法的调用抽象方法ExecuteCore
- 在Controller的ExecuteCore方法调用ActionInvoker(这个属性实现类是ControllerActionInvoker)的InvokeAction方法
- 执行MVC过滤器
- 调用控制器的方法,得到ActionResult
- 调用ActionResult的ExecuteResult方法
- Response输出
IController
public
interface
IController
{
void
Execute(RequestContext requestContext);
}
ControllerBase(精简源码)
protected
virtual
void
Execute(RequestContext requestContext)
{
this
.Initialize(requestContext);
using
(ScopeStorage.CreateTransientScope())
this
.ExecuteCore();
}
Controller
protected
override
void
ExecuteCore()
{
this
.PossiblyLoadTempData();
try
{
string
requiredString =
this
.RouteData.GetRequiredString(
"action"
);
if
(
this
.ActionInvoker.InvokeAction(
this
.ControllerContext, requiredString))
return
;
this
.HandleUnknownAction(requiredString);
}
finally
{
this
.PossiblySaveTempData();
}
}
ControllerActionInvoker
public
virtual
bool
InvokeAction(ControllerContext controllerContext,
string
actionName)
{
if
(controllerContext ==
null
)
throw
new
ArgumentNullException(
"controllerContext"
);
if
(
string
.IsNullOrEmpty(actionName))
throw
new
ArgumentException(MvcResources.Common_NullOrEmpty,
"actionName"
);
ControllerDescriptor controllerDescriptor =
this
.GetControllerDescriptor(controllerContext);
ActionDescriptor action =
this
.FindAction(controllerContext, controllerDescriptor, actionName);
if
(action ==
null
)
return
false
;
FilterInfo filters =
this
.GetFilters(controllerContext, action);
try
{
AuthorizationContext authorizationContext =
this
.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, action);
if
(authorizationContext.Result !=
null
)
{
this
.InvokeActionResult(controllerContext, authorizationContext.Result);
}
else
{
if
(controllerContext.Controller.ValidateRequest)
ControllerActionInvoker.ValidateRequest(controllerContext);
IDictionary<
string
,
object
> parameterValues =
this
.GetParameterValues(controllerContext, action);
ActionExecutedContext actionExecutedContext =
this
.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, action, parameterValues);
this
.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result);
}
}
catch
(ThreadAbortException ex)
{
throw
;
}
catch
(Exception ex)
{
ExceptionContext exceptionContext =
this
.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, ex);
if
(!exceptionContext.ExceptionHandled)
throw
;
else
this
.InvokeActionResult(controllerContext, exceptionContext.Result);
}
return
true
;
}
从这个方法中,也可以看出MVC过滤器的执行顺序.
(MVC没有WebForm的控件生命周期,但是提供过滤器实现类似效果性能更高.)
这个方法中的InvokeActionResult方法实际就是调用
protected
virtual
void
InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
{
actionResult.ExecuteResult(controllerContext);
}
也就到达我们最上面的ActionResult的抽象方法中了.
至此MVC核心源码分析结束了.
实现MVC
看完MVC源码,实现一个MVC源码也很简单,这里我们干脆把路由系统和MVC用到的类都实现出来,完全脱离System.MVC和System.Web.Routing2个程序集
代码效果
Global文件
public
class
Global : HttpApplication
{
protected
void
Application_Start(
object
sender, EventArgs e)
{
RouteTable.Routes.Add(
"default"
,
new
Route());
}
}
HomeController
public
class
HomeController : Controller
{
public
ActionResult Index()
{
return
Content(
"Hello World"
);
}
}
运行效果
性能
后台代码
点击下载
说明:本实现代码主要偏MVCHandle一块
扩展
从微软的源码中可以看出微软偏爱于AOP和面向接口的编程方式.
- [ASP.NET]分析MVC5源码,并实现一个ASP.MVC
- asp.net mvc源码分析-AsyncController
- asp.net mvc源码分析-ModelValidatorProviders
- asp.net mvc源码分析-EditorFor
- asp.net mvc源码分析-OutputCache
- ASP.NET WebForm / MVC 源码分析
- ASP .NET MVC5 添加一个控制器
- ASP.NET MVC5 实现分页查询
- ASP.NET MVC5 实现分页查询
- ASP.NET MVC5 实现分页查询
- ASP.NET MVC5 实现分页查询
- ASP.NET MVC5 实现分页查询
- asp.net mvc5 安装
- ASP.net MVC5 简介
- ASP.NET MVC 初学笔记.3 MVC5、EF、RDLC实现报表操作
- ASP.NET MVC 5-开始MVC5之旅
- ASP.NET MVC 5-开始MVC5之旅
- ASP.NET MVC 5-开始MVC5之旅
- sql查询语句的结果字段中有空值
- java中的基本数据类型存放位置
- Javascript学习(一)——汉诺塔迭代算法的实现过程
- C函数指针妙用,用c语言写一个简易类
- 基于AFNetWoring 封装的网络请求类
- [ASP.NET]分析MVC5源码,并实现一个ASP.MVC
- iOS 代码实践总结
- 设计模式学习笔记(二)代理模式
- Activity的启动过程
- Java中产生随机数的方法
- ES7之Decorators实现AOP示例
- 应用系统Url交互之数据加密
- 【4】Windows客户端C/C++编程规范“建议”——表达式和运算
- 【Unity】小地图遮罩Shader