Mvc对请求的处理机制

来源:互联网 发布:网络域名查询 编辑:程序博客网 时间:2024/06/04 19:57

MVC管道与ASP.net的管道机制大同小异


我们知道非MVC中都是一个扩展名对应一个Handler
而MVC请求的的地址是 http://www.mymvc.com/Home/Index 它并不像WebForm一样有扩展名,那么MVC是怎么处理用户请求的呢?
为了能够解析用户去请求,MVC只能通过两种手段,第一种就是Module,第二种就是Handler


根据这种思路,我们去看代码:
首先,网站启动的时候,会先执行Global.asax文件中的Application_Start()方法,

在这个方法里执行了 RouteConfig.RegisterRoutes(RouteTable.Routes);这段代码,这段代码注册路由

 public class RouteConfig {     public static void RegisterRoutes(RouteCollection routes)     {         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//表示要过滤掉的路由         routes.MapRoute( //正常的路由(在这里往RRouteCollection路由模板集合中添加了一个名字为Default的路由模板)             name: "Default",             url: "{controller}/{action}/{id}",             defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }         );     } }
既然我们定义了路由模板,那么必定会HttpModule截获,于是MVC就定义了一个UrlRoutingModule类,继承了IHttpModule,用于截获这个我们定义了的路由
在这个UrlRoutingModule类中的Init方法中注册了一个application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);事件用于处理,

在这个事件中的Init方法中,获取到了最终处理用户请求的MvcHandler,并激活了控制器。

namespace System.Web.Routing{[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]public class UrlRoutingModule : IHttpModule{private static readonly object _contextKey = new object();private static readonly object _requestDataKey = new object();private RouteCollection _routeCollection;public RouteCollection RouteCollection{get{if (this._routeCollection == null){this._routeCollection = RouteTable.Routes;}return this._routeCollection;}set{this._routeCollection = value;}}protected virtual void Dispose(){}protected virtual void Init(HttpApplication application){if (application.Context.Items[UrlRoutingModule._contextKey] != null){return;}application.Context.Items[UrlRoutingModule._contextKey] = UrlRoutingModule._contextKey;application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);}private void OnApplicationPostResolveRequestCache(object sender, EventArgs e){HttpApplication httpApplication = (HttpApplication)sender;HttpContextBase context = new HttpContextWrapper(httpApplication.Context);this.PostResolveRequestCache(context);}[Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]public virtual void PostMapRequestHandler(HttpContextBase context){}public virtual void PostResolveRequestCache(HttpContextBase context){RouteData routeData = this.RouteCollection.GetRouteData(context); //根据context,找到匹配的路由if (routeData == null){return;}IRouteHandler routeHandler = routeData.RouteHandler; //在这里获取到System.Web.Mvc.MvcRouteHandler,这个Handler工厂,还不是真正处理用户请求的Handlerif (routeHandler == null){throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));}if (routeHandler is StopRoutingHandler) //{//在Global.asax文件中 有一段RouteConfig.RegisterRoutes(RouteTable.Routes);代码,在这个RegisterRoutes方法中有一句routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//表示需要过滤掉的路由,而这个IgnoreRoute路由的Handler就是StopRoutingHandler,所以在这里做了判断,Handler是StopRoutingHandler则就不往下执行,直接return,不再处理这条请求//注:我们需要处理的 MapRoute路由的Handler是MvcRouteHandlerreturn;}RequestContext requestContext = new RequestContext(context, routeData);context.Request.RequestContext = requestContext;//在这里才真正拿到了处理用户请求的ystem.Web.Mvc.MvcHandler,并在这里面创建了控制器,执行了控制器IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); if (httpHandler == null){throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[]{routeHandler.GetType()}));}if (!(httpHandler is UrlAuthFailureHandler)){context.RemapHandler(httpHandler);return;}if (FormsAuthenticationModule.FormsAuthRequired){UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);return;}throw new HttpException(401, SR.GetString("Assess_Denied_Description3"));}void IHttpModule.Dispose(){this.Dispose();}void IHttpModule.Init(HttpApplication application){this.Init(application);}}}

在上面代码中执行了一段IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 代码,目的是拿到MvcHandler

那么我们就来到MvcRouteHandler 工厂类的GetHttpHandler(RequestContext requestContext)方法中一看究竟

protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext){requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));return new MvcHandler(requestContext);//在这里 创建了一个MvcHandler 返回}

既然上面拿到了MvcHandler,那么我们就一探究竟,来看看在MvcHandler里控制器的创建与执行

/// <summary>Processes the request by using the specified HTTP request context.</summary>/// <param name="httpContext">The HTTP context.</param>protected virtual void ProcessRequest(HttpContext httpContext){HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);this.ProcessRequest(httpContext2);}/// <summary>Processes the request by using the specified base HTTP request context.</summary>/// <param name="httpContext">The HTTP context.</param>protected internal virtual void ProcessRequest(HttpContextBase httpContext){IController controller;IControllerFactory controllerFactory;this.ProcessRequestInit(httpContext, out controller, out controllerFactory);try{controller.Execute(this.RequestContext);//将RequestContext作为参数,执行了控制器}finally{controllerFactory.ReleaseController(controller);}}private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory){HttpContext current = HttpContext.Current;if (current != null && ValidationUtility.IsValidationEnabled(current) == true){ValidationUtility.EnableDynamicValidation(current);}this.AddVersionHeader(httpContext);this.RemoveOptionalRoutingParameters();string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");factory = this.ControllerBuilder.GetControllerFactory(); //这个创建了控制器controller = factory.CreateController(this.RequestContext, requiredString);if (controller == null){throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]{factory.GetType(),requiredString}));}}

总结:其实MVC的架构是基于Module的




原创粉丝点击