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()

 具体参考过程

ASP.NET必须知道的:HttpModule,HttpHandler

 

 

下面简要描述下 asp.net mvc 处理流程:

 1、在Web. config中 注册


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

2、在Global中设置 System.Web.Routing.RouteTable.Routes 的值,应用于解析Url,得到相应的Controller,Action,和RouteData

ContractedBlock.gif ExpandedBlockStart.gif Code
 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

ContractedBlock.gif ExpandedBlockStart.gif Code
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;
        }

 

3、发送Http请求,因为在第1部注册了System.Web.Routing.UrlRoutingModule ,在执行到 HttpModule 时就调用IHttpModule接口的 Init 方法

ContractedBlock.gif ExpandedBlockStart.gif Code
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);下的代码

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

 

 

再看this.PostResolveRequestCache(context);的调用

ContractedBlock.gif ExpandedBlockStart.gif Code
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.Path, HttpHandler = httpHandler };我们把httpHandler 存入context.Items字段中。

 2) 我们看 Init 中的调用 application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler); 下的代码

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

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
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 = (RequestData) context.Items[_requestDataKey];得到了存入 RequestDataRequestData 对象,再通过 context.Handler = data.HttpHandler;设置处理Http请求的IhttpHandler对象,也就是MvcRouteHandler对象。

可以看出:1)我们得到了 MvcRouteHandler对象。2)我们把MvcRouteHandler对象赋给了context.Handler

4)进入出来http请求的 MvcRouteHandler对象

ContractedBlock.gif ExpandedBlockStart.gif Code
 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的处理代码

ContractedBlock.gif ExpandedBlockStart.gif Code
 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实现了IController接口,具体看看它的继承关系:

 

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

ContractedBlock.gif ExpandedBlockStart.gif Code
 protected virtual void Execute(RequestContext requestContext) {
            
if (requestContext == null) {
                
throw new ArgumentNullException("requestContext");
            }

            Initialize(requestContext);
            ExecuteCore();
        }

 

7、 在Execute方法中,调用了ExecuteCore,看看ExecuteCore的调用:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  protected abstract void ExecuteCore();

 

可以看出 ExecuteCore ,执行的是 Controller 中的方法。

ContractedBlock.gif ExpandedBlockStart.gif Code
 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对象。

看看代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
 public IActionInvoker ActionInvoker {
            
get {
                
if (_actionInvoker == null) {
                    _actionInvoker 
= new ControllerActionInvoker();
                }
                
return _actionInvoker;
            }
            
set {
                _actionInvoker 
= value;
            }
        }

 】

在ExecuteCore中,我们得到了action,并调用 ActionInvoker.InvokeAction(ControllerContext, actionName) 执行。

 8、看看 InvokeAction的代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
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;
        }

 

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


我们看看 ViewResultBase 对 ExecuteResult 的实现:


ContractedBlock.gif ExpandedBlockStart.gif Code
 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的实现:

ContractedBlock.gif ExpandedBlockStart.gif Code
 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);

在进入ViewEngineCollection.FindView看看:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
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);
        }

 

3)再看看看 ViewEngineCollection.FindView 中的Find调用:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  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);
        }

 

10) 最后看看 从控制器到输出的流程 (注:Model 随 ControllerContext 传递)

 


转载于:https://www.cnblogs.com/laiwen/archive/2009/03/04/1402862.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值