Dev_Eric

新浪微博:卖螃蟹的程序员

导航

ASP.NET MVC 流程概述 (转)

     在知道asp.net mvc 流程之前,必须知道完整的http请求在asp.net framework中的处理流 程: HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->Http Pipeline-->ASPNET_WP.EXE-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()

 1、在Web. config中 注册



<modules>
    
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    </modules>


 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Contact", action = "Index", id = "" }  // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }

 在MVC对RouteCollection 的扩展方法中,有MapRoute


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)
            };

            if ((namespaces != null&& (namespaces.Length > 0)) {
                route.DataTokens = new RouteValueDictionary();
                route.DataTokens["Namespaces"= namespaces;
            }

            routes.Add(name, route);

            return route;
        }

 

IHttpModule接口的 Init 方法


protected virtual void Init(HttpApplication application)
{
    application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
    application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
}

 

1)我们看 Init 中的调用 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);下的代码


private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
    HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
    this.PostResolveRequestCache(context);
}

 

 

PostResolveRequestCache(context);的调用


public virtual void PostResolveRequestCache(HttpContextBase context)
{
    RouteData routeData = this.RouteCollection.GetRouteData(context);
    if (routeData != null)
    {
        IRouteHandler routeHandler = routeData.RouteHandler;
        if (routeHandler == null)
        {
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
        }
        if (!(routeHandler is StopRoutingHandler))
        {
            RequestContext requestContext = new RequestContext(context, routeData);
            IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
            if (httpHandler == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
            }
            context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };
            context.RewritePath("~/UrlRouting.axd");
        }
    }
}

 

 

IRouteHandler routeHandler = routeData.RouteHandler;  行把routeHandler赋了具体值。但 routeData.RouteHandler如何来的? 在第2部MapRoute的调用中,我们得到了它。通过routeHandler,我们得到了 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);然后,通过context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.PathHttpHandler = httpHandler };我们把httpHandler 存入context.Items字段中。

application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler); 下的代码


private void OnApplicationPostMapRequestHandler(object sender, EventArgs e)
{
    HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
    this.PostMapRequestHandler(context);
}

 

 


public virtual void PostMapRequestHandler(HttpContextBase context)
{
    RequestData data = (RequestData) context.Items[_requestDataKey];
    if (data != null)
    {
        context.RewritePath(data.OriginalPath);
        context.Handler = data.HttpHandler;
    }
}

 

 

 我们通过 RequestData data = (RequestDatacontext.Items[_requestDataKey];得到了存入 RequestDataRequestData 对象,再通过context.Handler = data.HttpHandler;设置处理Http请求的IhttpHandler对象,也就是MvcRouteHandler对象。

context.Handler


 public class MvcRouteHandler : IRouteHandler {
        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
            return new MvcHandler(requestContext);
        }

        #region IRouteHandler Members
        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
            return GetHttpHandler(requestContext);
        }
        #endregion
    }

 

通过 return new MvcHandler(requestContext); 我们发现,MvcRouteHandler 的作用是选择执行控制器操作的 IHttpHandler。

 

 5、我们看MvcHandler的处理代码


 protected internal virtual void ProcessRequest(HttpContextBase httpContext) {
            AddVersionHeader(httpContext);

            // Get the controller type
            string controllerName = RequestContext.RouteData.GetRequiredString("controller");

            // Instantiate the controller and call Execute
            IControllerFactory factory = ControllerBuilder.GetControllerFactory();
            IController controller = factory.CreateController(RequestContext, controllerName);
            if (controller == null) {
                throw new InvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentUICulture,
                        MvcResources.ControllerBuilder_FactoryReturnedNull,
                        factory.GetType(),
                        controllerName));
            }
            try {
                controller.Execute(RequestContext);
            }
            finally {
                factory.ReleaseController(controller);
            }
        }

 

6、controller.Execute(RequestContext);这一步是关键,它的作用是得到控制器,并执行。

 

 原来 controller.Execute(RequestContext) 执行的是ControllerBase的Execute,我们进入看看:


 protected virtual void Execute(RequestContext requestContext) {
            if (requestContext == null) {
                throw new ArgumentNullException("requestContext");
            }

            Initialize(requestContext);
            ExecuteCore();
        }

 

 


  protected abstract void ExecuteCore();

 


 protected override void ExecuteCore() {
            TempData.Load(ControllerContext, TempDataProvider);

            try {
                string actionName = RouteData.GetRequiredString("action");
                if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
                    HandleUnknownAction(actionName);
                }
            }
            finally {
                TempData.Save(ControllerContext, TempDataProvider);
            }
        }

 附近说明:【 ActionInvoker 的实际对象是实现 IActionInvoker 接口的对象,默认为 ControllerActionInvoker对象。


 public IActionInvoker ActionInvoker {
            get {
                if (_actionInvoker == null) {
                    _actionInvoker = new ControllerActionInvoker();
                }
                return _actionInvoker;
            }
            set {
                _actionInvoker = value;
            }
        }

 】

 8、看看 InvokeAction的代码:

 


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 = GetControllerDescriptor(controllerContext);
            ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
            if (actionDescriptor != null) {
                FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);

                try {
                    AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                    if (authContext.Result != null) {
                        // the auth filter signaled that we should let it short-circuit the request
                        InvokeActionResult(controllerContext, authContext.Result);
                    }
                    else {
                        if (controllerContext.Controller.ValidateRequest) {
                            ValidateRequest(controllerContext.HttpContext.Request);
                        }

                        IDictionary<stringobject> parameters = GetParameterValues(controllerContext, actionDescriptor);
                        ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
                        InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
                    }
                }
                catch (ThreadAbortException) {
                    // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                    // the filters don't see this as an error.
                    throw;
                }
                catch (Exception ex) {
                    // something blew up, so execute the exception filters
                    ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                    if (!exceptionContext.ExceptionHandled) {
                        throw;
                    }
                    InvokeActionResult(controllerContext, exceptionContext.Result);
                }

                return true;
            }

            // notify controller that no method matched
            return false;
        }

 

InvokeActionResult 其实就是反射调用 ActionResult 的  public abstract void ExecuteResult(ControllerContext context); 方法。

我们看看 ViewResultBase 对 ExecuteResult 的实现:


 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) {
                result = FindView(context);
                View = result.View;
            }

            ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
            View.Render(viewContext, context.HttpContext.Response.Output);

            if (result != null) {
                result.ViewEngine.ReleaseView(context, View);
            }
        }

 

1)进入 result = FindView(context); 其实 调用的是ViewResult的FindView的实现:


 protected override ViewEngineResult FindView(ControllerContext context) {
            ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
            if (result.View != null) {
                return result;
            }

            // we need to generate an exception containing all the locations we searched
            StringBuilder locationsText = new StringBuilder();
            foreach (string location in result.SearchedLocations) {
                locationsText.AppendLine();
                locationsText.Append(location);
            }
            throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
                MvcResources.Common_ViewNotFound, ViewName, locationsText));
        }

 

2) 看看 FindView中的第一行代码 ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);

 


public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName) {
            if (controllerContext == null) {
                throw new ArgumentNullException("controllerContext");
            }
            if (string.IsNullOrEmpty(viewName)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
            }
            Func<IViewEngine, ViewEngineResult> cacheLocator = e => e.FindView(controllerContext, viewName, masterName, true);
            Func<IViewEngine, ViewEngineResult> locator = e => e.FindView(controllerContext, viewName, masterName, false);
            return Find(cacheLocator, locator);
        }

 

  


  private ViewEngineResult Find(Func<IViewEngine, ViewEngineResult> cacheLocator, Func<IViewEngine, ViewEngineResult> locator) {
            ViewEngineResult result;

            foreach (IViewEngine engine in Items) {
                if (engine != null) {
                    result = cacheLocator(engine);

                    if (result.View != null) {
                        return result;
                    }
                }
            }

            List<string> searched = new List<string>();

            foreach (IViewEngine engine in Items) {
                if (engine != null) {
                    result = locator(engine);

                    if (result.View != null) {
                        return result;
                    }

                    searched.AddRange(result.SearchedLocations);
                }
            }

            return new ViewEngineResult(searched);
        }

 

 

posted on 2016-01-02 21:09  Dev_Eric  阅读(206)  评论(0)    收藏  举报