ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)
2020-12-13 15:01
标签:des style class blog code http 在上一篇"ASP.NET MVC请求处理管道生命周期的19个关键环节(7-12) ",体验了7-12关键环节,本篇继续。 ⒀当请求到达UrlRoutingModule的时候,UrlRoutingModule取出请求中的Controller、Action等RouteData信息,与路由表中的所有规则进行匹配,若匹配,把请求交给IRouteHandler,即MVCRouteHandler MVCRouteHandler是用来生成实现IHttpHandler接口的MvcHandler: UrlRoutingModule如何把请求交给MVCRouteHandler? //通过RouteCollection的静态方法GetRouteData获取到封装路由信息的RouteData实例 //再从RouteData中获取MVCRouteHandler 为什么可以从RouteData中拿到MVCRouteHadnler呢? ⒁MVCRouteHandler把请求交给MvcHandler 还是从UrlRoutingModule的源码可以看到,通过HttpHandler的GetHttpHandler()方法获取到了实现了IHttpHandler接口的MVCHandler: MvcHandler的部分源码为: ⒂从以上可以看出:首先通过ControllerBuilder的静态方法GetControllerFactory获取到实现IControllerFactory接口的ControllerFactory,然后根据从上下文中的路由数据中拿到controller名称,并据此创建实现IController接口的Controller Controller派生于ControllerBase, 而ControllerBase实现了IController接口。ControllerBase的部分源码如下: 从中可以看成: ⒃ActionInvoker激发Action方法 ActionInvoker实现了IActionInvoker接口: MVC默认的ActionInvoker是ControllerActionInvoker。 在Controller类中,提供了类型为IActionInvoker的属性ActionInvoker,当执行ExecuteCore()方法时会让这个ActionInvoker调用InvokeAction()方法激发Action。如下:
另外,ActionDescriptor还提供了一个FindAction()方法,用来找到需要被执行的Action。 ⒄ActionInvoker在执行InvokeAction()方法返回ActionResult ActionResult是一个抽象类: 如果ActionResult是非ViewResult,比如JsonResult, ContentResult,这些内容将直接被输送到Response响应流中,显示给客户端;如果是ViewResult,就会进入下一个渲染视图环节。 ⒅ViewEngine找到需要被渲染的视图 默认的有Razor View Engine和Web Form View Engine,实现IViewEngine接口。 IViewEngine接口方法: 如果要创建自定义View Engine,只需要派生于VirtualPathProviderViewEngine这个类。 ⒆View被加载成WebViewPage 调用ViewResult的ExecuteResult()方法,通过IView的Render()方法渲染成Html。 completed~~ ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19),搜素材,soscw.com ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19) 标签:des style class blog code http 原文地址:http://www.cnblogs.com/darrenji/p/3795690.htmlnamespace System.Web.Routing
{
public interface IRouteHandler
{
IHttpHandler GetHttpHandler(RequestContext requestContext);
}
}
通过分析UrlRoutingModule的源码可以看到:
RouteData routeData = this.RouteCollection.GetRouteData(context);
IRouteHandler routeHandler = routeData.RouteHandler;
因为当我们在HttpApplication的第一个管道事件,使用MapRoute()方法注册路由的时候,已经通过Route类的构造函数把MVCRouteHandler注入到路由中了。public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
if (routes == null) {
throw new ArgumentNullException("routes");
}
if (url == null) {
throw new ArgumentNullException("url");
}
Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
if ((namespaces != null) && (namespaces.Length > 0)) {
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
context.RemapHandler(httpHandler);
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
SecurityUtil.ProcessInApplicationTrust(() =>
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);//初始化了ControllerFactory
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
});
}
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) {
bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current);
if (isRequestValidationEnabled == true) {
ValidationUtility.EnableDynamicValidation(HttpContext.Current);
}
AddVersionHeader(httpContext);
RemoveOptionalRoutingParameters();
string controllerName = RequestContext.RouteData.GetRequiredString("controller");
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);
if (controller == null) {
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,MvcResources.ControllerBuilder_FactoryReturnedNull,factory.GetType(),controllerName));
}
}
}
public abstract class ControllerBase : IController
{
protected virtual void Execute(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
if (requestContext.HttpContext == null)
{
throw new ArgumentException(
MvcResources.ControllerBase_CannotExecuteWithNullHttpContext,
"requestContext");
}
VerifyExecuteCalledOnce();
Initialize(requestContext);
using (ScopeStorage.CreateTransientScope())
{
ExecuteCore();
}
}
protected abstract void ExecuteCore();
......
}
● 每次调用controller,都会执行基类ControllerBase的Execute()方法
● Execute()方法又会调用ExecuteCore()这个抽象方法
● ExecuteCore()这个抽象方法的实现被定义在Controller中
● 在Controller中的ExecuteCore()方法会调用ActionInvoker的InvokeAction()方法public interface IActionInvoker
{
bool InvokeAction(ControllerContext controllerContext, string actionName);
}
public class Controller
{
......
private IActionInvoker _actionInvoker;
public IActionInvoker ActionInvoker
{
get
{
if(_actionInvoker == null)
{
_actionInvoker = CreateActionInvoker();
}
return _actionInvoker;
}
set
{
_actionInvoker = value;
}
}
protected virtual IActionInvoker CreateActionInvoker()
{
return new ControllerActionInvoker();
}
public override void ExecuteCore()
{
ActionInvoker.InvokeAction(...);
}
.....
}
ActionInvoker在执行InvokeAction()方法时会需要有关Controller和Action的相关信息,实际上,Controller信息(比如Controller的名称、类型、包含的Action等)被封装在ControllerDescriptor这个类中,Action信息(比如Action的名称、参数、属性、过滤器等)被封装在ActionDescriptor中。
public abstract class ActionResult
{
public abstract void ExecuteResult(ControllerContext context);
}
● FindPartialView
● FindView
● ReleaseViewpublic abstract class ViewResultBase : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (String.IsNullOrEmpty(ViewName))
{
ViewName = context.RouteData.GetRequiredString("action");
}
ViewEngineResult result = null;
if (View == null)
{
//通过视图引擎获取到ViewEngineResult ,此时模板页面【aspx】被加载成了WebViewPage
文章标题:ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)
文章链接:http://soscw.com/essay/34724.html