时间:2021-07-01 10:21:17 帮助过:23人阅读
- <br>protected virtual void Init(HttpApplication application) <br>{ <br>if (application.Context.Items[_contextKey] == null) <br>{ <br>application.Context.Items[_contextKey] = _contextKey; <br>application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); <br>} <br>} <br><br>private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) <br>{ <br>HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context); <br>this.PostResolveRequestCache(context); <br>} <br><br>public virtual void PostResolveRequestCache(HttpContextBase context) <br>{ <br>RouteData routeData = this.RouteCollection.GetRouteData(context); <br>if (routeData != null) <br>{ <br>IRouteHandler routeHandler = routeData.RouteHandler; <br>if (routeHandler == null) <br>{ <br>throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0])); <br>} <br>if (!(routeHandler is StopRoutingHandler)) <br>{ <br>RequestContext requestContext = new RequestContext(context, routeData); <br>context.Request.RequestContext = requestContext; <br>IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); <br>if (httpHandler == null) <br>{ <br>throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() })); <br>} <br>if (httpHandler is UrlAuthFailureHandler) <br>{ <br>if (!FormsAuthenticationModule.FormsAuthRequired) <br>{ <br>throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3")); <br>} <br>UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this); <br>} <br>else <br>{ <br>context.RemapHandler(httpHandler); <br>} <br>} <br>} <br>} <br> <br>在IHttpModule.Init中注册了一个PostResolveRequestCache事件,而该事件主要是调用PostResolveRequestCache这个方法,在这个方法里面有几句很重要的代码是 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>RouteData routeData = this.RouteCollection.GetRouteData(context); <br>IRouteHandler routeHandler = routeData.RouteHandler; <br>RequestContext requestContext = new RequestContext(context, routeData); <br>context.Request.RequestContext = requestContext; <br>IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); <br>context.RemapHandler(httpHandler); <br> <br>让我们来分析第一句RouteData routeData = this.RouteCollection.GetRouteData(context) ,这句我们猜测是获取路由信息。要想理解这句代码又得回到我们程序中来,我们在Global.asax.cs文件中的RegisterRoutes方法中,默认有这么一句 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>routes.MapRoute( <br>"Default", // 路由名称 <br>"{controller}/{action}/{id}", // 带有参数的 URL <br>new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 <br>); <br> <br>这句代码主要是注册一个路由,这里的url要注意不能随便写,需要有controller和action。具体是怎么实现的了? <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { <br>Route route = new Route(url, new MvcRouteHandler()) { <br>Defaults = new RouteValueDictionary(defaults), <br>Constraints = new RouteValueDictionary(constraints), <br>DataTokens = new RouteValueDictionary() <br>}; <br><br>if ((namespaces != null) && (namespaces.Length > 0)) { <br>route.DataTokens["Namespaces"] = namespaces; <br>} <br>routes.Add(name, route); <br>return route; <br>} <br> <br>各参数如下 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>routeName="Default", // 路由名称 <br>routeUrl= "{controller}/{action}/{id}", // 带有参数的 URL <br>defaults=new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 <br>constraints=null <br>namespaces=null <br> <br>在这里创建了一个Route实例并且把它加入到RouteCollection中了。 <br>现在又让我们回到 RouteData routeData = this.RouteCollection.GetRouteData(context);这句代码中来,GetRouteData的主要代码如下: <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>public RouteData GetRouteData(HttpContextBase httpContext) <br>{ <br>using (this.GetReadLock()) <br>{ <br>foreach (RouteBase base2 in this) <br>{ <br>RouteData routeData = base2.GetRouteData(httpContext); <br>if (routeData != null) <br>{ <br>return routeData; <br>} <br>} <br>} <br>return null; <br>} <br> <br>在这里的base2就是我们先前调用MapRoute是添加的Route的。而Route的GetRouteData的方法如下: <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>public override RouteData GetRouteData(HttpContextBase httpContext) <br>{ <br>string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; <br>RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults); <br>if (values == null) <br>{ <br>return null; <br>} <br>RouteData data = new RouteData(this, this.RouteHandler); <br>if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) <br>{ <br>return null; <br>} <br>foreach (KeyValuePair<string, object> pair in values) <br>{ <br>data.Values.Add(pair.Key, pair.Value); <br>} <br>if (this.DataTokens != null) <br>{ <br>foreach (KeyValuePair<string, object> pair2 in this.DataTokens) <br>{ <br>data.DataTokens[pair2.Key] = pair2.Value; <br>} <br>} <br>return data; <br>} <br> <br>这个方法很复杂,有许多验证和检查,我们主要关心一句 RouteData data = new RouteData(this, this.RouteHandler); <br>当然剩下 RequestContext requestContext = new RequestContext(context, routeData); <br>context.Request.RequestContext = requestContext;这2句没什么特别了。 <br>现在让我们来看看IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);这句究竟干了些什么,意思很明白获取Httphandler。 <br>那么MvcRouteHandler是如何获取一个Httphandler的了, <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { <br>requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext)); <br>return new MvcHandler(requestContext); <br>} <br> <br>直接返回了一个MvcHandler实例。 <br>最有一句context.RemapHandler(httpHandler); 很简单很好明白吧,在HttpContext的RemapHandler方法中有这么一句 this._remapHandler = handler; <br>在HttpContext中有这个属性 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>internal IHttpHandler RemapHandlerInstance <br>{ <br>get <br>{ <br>return this._remapHandler; <br>} <br>} <br> <br>那么这个东西又是什么时候调用的了,在HttpApplication的内部类MaterializeHandlerExecutionStep中的 void HttpApplication.IExecutionStep.Execute()方法调用 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>if (httpContext.RemapHandlerInstance != null) <br>{ <br>httpContext.Handler = httpContext.RemapHandlerInstance; <br>} <br> <br>看到MaterializeHandlerExecutionStep这个了类名,我想大家都能猜到吧。在内部类PipelineStepManager中BuildSteps方法有 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app); <br>app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step); <br> <br>我想大家看到这里对mvc整个路由应该有个大致的理解了吧。</li><li> </li><li> </li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre></li></ol></pre>