• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    asp.net mvc路由篇 如何找到 IHttpHandler方法介绍
    学习是使用asp.net已经有很长一段时间了,现在就来分析一下mvc的整过过程吧。个人计划写一个mvc系列的博文,仅从源代码的角度来分析mvc。在接触mvc时我们一定会经历路由,那么路由这东东是怎么搞出来的啊。在我们的web.config中有这么一句: add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 看来路由是它咋负责了。在这个dll中有一个很特殊的类UrlRoutingModule
    我们来看看它里面主要的核心代码吧:
    复制代码 代码如下:

    protected virtual void Init(HttpApplication application)
    {
    if (application.Context.Items[_contextKey] == null)
    {
    application.Context.Items[_contextKey] = _contextKey;
    application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
    }
    }

    private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
    {
    HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
    this.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, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
    }
    if (!(routeHandler is StopRoutingHandler))
    {
    RequestContext requestContext = new RequestContext(context, routeData);
    context.Request.RequestContext = requestContext;
    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)
    {
    if (!FormsAuthenticationModule.FormsAuthRequired)
    {
    throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
    }
    UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
    }
    else
    {
    context.RemapHandler(httpHandler);
    }
    }
    }
    }

    在IHttpModule.Init中注册了一个PostResolveRequestCache事件,而该事件主要是调用PostResolveRequestCache这个方法,在这个方法里面有几句很重要的代码是
    复制代码 代码如下:

    RouteData routeData = this.RouteCollection.GetRouteData(context);
    IRouteHandler routeHandler = routeData.RouteHandler;
    RequestContext requestContext = new RequestContext(context, routeData);
    context.Request.RequestContext = requestContext;
    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
    context.RemapHandler(httpHandler);

    让我们来分析第一句RouteData routeData = this.RouteCollection.GetRouteData(context) ,这句我们猜测是获取路由信息。要想理解这句代码又得回到我们程序中来,我们在Global.asax.cs文件中的RegisterRoutes方法中,默认有这么一句
    复制代码 代码如下:

    routes.MapRoute(
    "Default", // 路由名称
    "{controller}/{action}/{id}", // 带有参数的 URL
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
    );

    这句代码主要是注册一个路由,这里的url要注意不能随便写,需要有controller和action。具体是怎么实现的了?
    复制代码 代码如下:

    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
    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;
    }

    各参数如下
    复制代码 代码如下:

    routeName="Default", // 路由名称
    routeUrl= "{controller}/{action}/{id}", // 带有参数的 URL
    defaults=new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
    constraints=null
    namespaces=null

    在这里创建了一个Route实例并且把它加入到RouteCollection中了。
    现在又让我们回到 RouteData routeData = this.RouteCollection.GetRouteData(context);这句代码中来,GetRouteData的主要代码如下:
    复制代码 代码如下:

    public RouteData GetRouteData(HttpContextBase httpContext)
    {
    using (this.GetReadLock())
    {
    foreach (RouteBase base2 in this)
    {
    RouteData routeData = base2.GetRouteData(httpContext);
    if (routeData != null)
    {
    return routeData;
    }
    }
    }
    return null;
    }

    在这里的base2就是我们先前调用MapRoute是添加的Route的。而Route的GetRouteData的方法如下:
    复制代码 代码如下:

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
    string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
    RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
    if (values == null)
    {
    return null;
    }
    RouteData data = new RouteData(this, this.RouteHandler);
    if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
    {
    return null;
    }
    foreach (KeyValuePairstring, object> pair in values)
    {
    data.Values.Add(pair.Key, pair.Value);
    }
    if (this.DataTokens != null)
    {
    foreach (KeyValuePairstring, object> pair2 in this.DataTokens)
    {
    data.DataTokens[pair2.Key] = pair2.Value;
    }
    }
    return data;
    }

    这个方法很复杂,有许多验证和检查,我们主要关心一句 RouteData data = new RouteData(this, this.RouteHandler);
    当然剩下 RequestContext requestContext = new RequestContext(context, routeData);
    context.Request.RequestContext = requestContext;这2句没什么特别了。
    现在让我们来看看IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);这句究竟干了些什么,意思很明白获取Httphandler。
    那么MvcRouteHandler是如何获取一个Httphandler的了,
    复制代码 代码如下:

    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
    requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
    return new MvcHandler(requestContext);
    }

    直接返回了一个MvcHandler实例。
    最有一句context.RemapHandler(httpHandler); 很简单很好明白吧,在HttpContext的RemapHandler方法中有这么一句 this._remapHandler = handler;
    在HttpContext中有这个属性
    复制代码 代码如下:

    internal IHttpHandler RemapHandlerInstance
    {
    get
    {
    return this._remapHandler;
    }
    }

    那么这个东西又是什么时候调用的了,在HttpApplication的内部类MaterializeHandlerExecutionStep中的 void HttpApplication.IExecutionStep.Execute()方法调用
    复制代码 代码如下:

    if (httpContext.RemapHandlerInstance != null)
    {
    httpContext.Handler = httpContext.RemapHandlerInstance;
    }

    看到MaterializeHandlerExecutionStep这个了类名,我想大家都能猜到吧。在内部类PipelineStepManager中BuildSteps方法有
    复制代码 代码如下:

    HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
    app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);

    我想大家看到这里对mvc整个路由应该有个大致的理解了吧。
    您可能感兴趣的文章:
    • ASP.NET Core MVC 配置全局路由前缀
    • 解读ASP.NET 5 & MVC6系列教程(11):Routing路由
    • 为ASP.NET MVC及WebApi添加路由优先级
    • ASP.NET MVC3关于生成纯静态后如何不再走路由直接访问静态页面
    • ASP.NET Core中使用默认MVC路由的配置
    上一篇:ASP.NET MVC Web API HttpClient简介
    下一篇:C#与.net高级编程 C#的多态介绍
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    asp.net mvc路由篇 如何找到 IHttpHandler方法介绍 asp.net,mvc,路由,篇,如何,