上一篇了解了 ISAPI执行原理,现在我们接着看 请求在MVC中是怎么处理的;
在了解MVC流程之前,我们先来了解一下一个重要的MvcHandler 类型,他是由路由生成的;
一. 路由模块
路由模块存在于 System.Web.Routing.dll 类库中,其中有一个重要的类 UrlRoutingModule;
- 网站配置主要分两种,全局和本站的Web.config配置;
1.1. 全局配置目录D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
<httpModules>
.......
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
.......
</httpModules>
1.2. 本站配置存在,应用程序的根目录下;
- 当请求管道接收到请求时,就会加载UrlRoutingModule,我们看内部怎么处理。我们看到在第七个管道事件PostResolveRequestCache中注册了一个事件;
public class UrlRoutingModule : IHttpModule
{
protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
//第七个管道事件
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}
private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication) sender;
HttpContextBase context = new HttpContextWrapper(application.Context);
this.PostResolveRequestCache(context);
}
public virtual void PostResolveRequestCache(HttpContextBase context)
{
//在RouteCollection中封装了所有的路由信息
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData != null)
{
// IRouteHandler 拿到具体的handle
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, System.Web.SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, System.Web.SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() }));
}
if (httpHandler is UrlAuthFailureHandler)
{
if (!FormsAuthenticationModule.FormsAuthRequired)
{
throw new HttpException(0x191, System.Web.SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
}
else
{
context.RemapHandler(httpHandler);
}
}
}
}
......
2.1. 在Application_Strat方法 路由注册中通过方法MapRoute将请求的地址写入RouteCollection中。
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
......
Route item = new Route(url, new MvcRouteHandler()) {
Defaults = CreateRouteValueDictionary(defaults),
Constraints = CreateRouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
if ((namespaces != null) && (namespaces.Length > 0))
{
item.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, item);
return item;
}
2.2. 通过方法 routeHandler.GetHttpHandler(requestContext) 实例MvcHandler的生成
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
return new MvcHandler(requestContext);
}
二.从MvcHandler的PR方法进入MVC流程的执行
一.Controller创建流程
以上介绍了MvcHandler在第七个事件中生成,在第11和12个事件之中调用PR方法开始响应请求,以下介绍PR中到底执行了什么;
- 通过ProcessRequestInit内部的工厂方法this.ControllerBuilder.GetControllerFactory().CreateController() 带入上下文对象创建Controller实例
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
this.ProcessRequestInit(httpContext, out controller, out factory);
try
{
controller.Execute(this.RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
}
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
HttpContext current = HttpContext.Current;
......
factory = this.ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(this.RequestContext, requiredString);
......
}
- 调用 controller.Execute(this.RequestContext)执行具体的Action; 通过ControllerBase的ExecuteCore 方法执行
public abstract class ControllerBase : IController
{
......
protected virtual void Execute(RequestContext requestContext)
{
......
using (ScopeStorage.CreateTransientScope())
{
this.ExecuteCore();
}
......
}
3.调用Controller的ExecuteCore().GetRequiredString()方法;获取Action方法名称,并通过ExecuteCore().InvokeAction()触发.
3.1. 可以看到在InvokeAction.FindAction()方法中根据上下文,方法名 寻找对应的描述或特性;
3.2. 可以看到在InvokeAction.GetFilters()方法中加载过滤器
public abstract class Controller
{
protected override void ExecuteCore()
{
this.PossiblyLoadTempData();
try
{
string requiredString = this.RouteData.GetRequiredString("action");
if (!this.ActionInvoker.InvokeAction(base.ControllerContext, requiredString))
{
this.HandleUnknownAction(requiredString);
}
}
finally
{
this.PossiblySaveTempData();
}
}
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
......
ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);
if (actionDescriptor == null)
{
return false;
}
FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);
try
{
AuthorizationContext context = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);
......
- 通过InvokeActionMethodWithFilters方法得到了一个Result对象;我们具体来看先通过actionDescriptor.Execute()生成结果,最后转为 ActionResult对象返回
protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
Func<ActionExecutedContext> seed = ()
=> new ActionExecutedContext(controllerContext, actionDescriptor, false, null)
{
Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
return filters.Reverse<IActionFilter>().Aggregate<IActionFilter, Func<ActionExecutedContext>>(seed, (next, filter) => () => InvokeActionMethodFilter(filter, preContext, next))();
}
protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
//此处执行action方法
object actionReturnValue = actionDescriptor.Execute(controllerContext, parameters);
return this.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue);
}
protected virtual ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
{
ActionResult result;
if (actionReturnValue == null)
{
return new EmptyResult();
}
//子类转基类返回
if (actionReturnValue as ActionResult)
{
result = actionReturnValue as ActionResult;
}
else
{
ContentResult result2 = new ContentResult {
Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture)
};
result = result2;
}
return result;
}
- 继续执行InvokeActionResultWithFilters方法完成Result的 AOP;
protected virtual ResultExecutedContext InvokeActionResultWithFilters(ControllerContext controllerContext, IList<IResultFilter> filters, ActionResult actionResult)
{
ResultExecutingContext preContext = new ResultExecutingContext(controllerContext, actionResult);
Func<ResultExecutedContext> seed = delegate {
this.InvokeActionResult(controllerContext, actionResult);
return new ResultExecutedContext(controllerContext, actionResult, false, null);
};
return filters.Reverse<IResultFilter>().Aggregate<IResultFilter, Func<ResultExecutedContext>>(seed, (next, filter) => () => InvokeActionResultFilter(filter, preContext, next))();
}
二.View创建流程
ActionResult已经拿到,现在要对其进行渲染;我们看一下它内部的渲染方法
- 通过ActionResult基类ActionResultBase.ExecuteResult()方法,看到创建一个 ViewEngineResult渲染引擎
public override void ExecuteResult(ControllerContext context)
{
......
if (string.IsNullOrEmpty(this.ViewName))
{
this.ViewName = context.RouteData.GetRequiredString("action");
}
ViewEngineResult result = null;
if (this.View == null)
{
result = this.FindView(context);
this.View = result.View;
}
- 通过ViewContext方法加载ViewData,TempData 等等数据生成ViewContext
public override void ExecuteResult(ControllerContext context)
{
......
TextWriter output = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
this.View.Render(viewContext, output);
......
}
public ViewContext(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer) : base(controllerContext)
{
this._defaultFormContext = new System.Web.Mvc.FormContext();
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (view == null)
{
throw new ArgumentNullException("view");
}
if (viewData == null)
{
throw new ArgumentNullException("viewData");
}
if (tempData == null)
{
throw new ArgumentNullException("tempData");
}
if (writer == null)
{
throw new ArgumentNullException("writer");
}
this.View = view;
this.ViewData = viewData;
this.Writer = writer;
this.TempData = tempData;
}
- 当上下文ViewContext,TextWriter已经准备好就可以渲染View了;我们从View.Render(viewContext, output)方法中看到,根据View类型生成类实例;
public void Render(ViewContext viewContext, TextWriter writer)
{
......
Type compiledType = this.BuildManager.GetCompiledType(this.ViewPath);
if (compiledType != null)
{
instance = this.ViewPageActivator.Create(this._controllerContext, compiledType);
}
......
this.RenderView(viewContext, writer, instance);
}
- 我们看到从RenderView方法中生成WebViewPage 对象,并将返回数据写入对象属性中,最后调用ExecutePageHierarchy渲染;至此整个View渲染流程就结束了;
protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
WebViewPage page = instance as WebViewPage;
if (page == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { base.ViewPath }));
}
page.OverridenLayoutPath = this.LayoutPath;
page.VirtualPath = base.ViewPath;
page.ViewContext = viewContext;
page.ViewData = viewContext.ViewData;
page.InitHelpers();
if (this.VirtualPathFactory != null)
{
page.VirtualPathFactory = this.VirtualPathFactory;
}
if (this.DisplayModeProvider != null)
{
page.DisplayModeProvider = this.DisplayModeProvider;
}
WebPageRenderingBase startPage = null;
if (this.RunViewStartPages)
{
startPage = this.StartPageLookup(page, RazorViewEngine.ViewStartFileName, this.ViewStartFileExtensions);
}
HttpContextBase httpContext = viewContext.HttpContext;
WebPageRenderingBase base4 = null;
object model = null;
page.ExecutePageHierarchy(new WebPageContext(httpContext, base4, model), writer, startPage);
}
参考文档 :
博客园:[http://www.cnblogs.com/edisonchou/p/4226558.html]
博客园:[http://www.cnblogs.com/yinzixin/archive/2012/12/05/2799459.html]