zoukankan      html  css  js  c++  java
  • MVC源码解析

    从前面篇章的解析, 其实能看的出来, IHttpModule 可以注册很多个, 而且可以从web.config注册, 可以动态注册. 但是有一个关键性的Module没有讲, 这里就先来讲一下这个关键性的Module -- UrlRoutingModule

    [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
    public class UrlRoutingModule : IHttpModule
    {
        // Fields
        private static readonly object _contextKey;
        private static readonly object _requestDataKey;
        private RouteCollection _routeCollection;
    
        // Methods
        static UrlRoutingModule();
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        public UrlRoutingModule();
        protected virtual void Dispose();
        protected virtual void Init(HttpApplication application);
        private void OnApplicationPostResolveRequestCache(object sender, EventArgs e);
        [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);
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        void IHttpModule.Dispose();
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        void IHttpModule.Init(HttpApplication application);
    
        // Properties
        public RouteCollection RouteCollection { get; [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set; }
    }

    来看一下他的Init方法, 注册了什么进去.

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

    从上一篇的那个事件图上可以看到, 这个是注册在缓存检查结束的事件上. 在看这个注册的方法之前, 还需要讲点别的. 因为在执行这个方法之前, 先执行的 Application_Start方法, 在这个方法中, 我们创建了路由表. 并在路由表中加入了匹配的路由规则.

    那先来讲一下路由注册吧.

    一、路由注册

     路由注册这里, 分为一般理由注册,区域路由注册,api路由注册. 这里只介绍一般路由注册, 其实是一样的, 只是注册的匹配规则不同而已.

    在Application_Start方法中, 路由注册就是下面这句话了.

    RouteConfig.RegisterRoutes(RouteTable.Routes);

    先来看一下, 这个方法的参数.

    // 摘要: 
    //     存储应用程序的 URL 路由。
    [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, 
      Culture=Neutral, PublicKeyToken=31bf3856ad364e35
    ")] public class RouteTable { // 摘要: // 初始化 System.Web.Routing.RouteTable 类的新实例。 public RouteTable(); // 摘要: // 获取从 System.Web.Routing.RouteBase 类派生的对象的集合。 // // 返回结果: // 包含集合中的所有路由的对象。 public static RouteCollection Routes { get; } }

    从这里能看到, 其实他传的是一个静态路由集合, 封装成了一个路由表.

    接下来就进入这个方法来看一下.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            constraints: new { controller=@"^w+$", id=@"^d+$" } //可以不写, 这里是对名称和参数的约束
        );
    }

    这里的IgnoreRoute就不看了, 直接看MapRoute方法, 这个方法是存放在静态扩展类中的: RouteCollectionExtensions 

    里面有很多的重载, 我只看那个参数最多的方法吧.

    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 item = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { item.DataTokens["Namespaces"] = namespaces; } routes.Add(name, item); return item; }

    这里就是解析参数, 并创建路由存入路由集合中, 即存入路由表中.

    1. 这里出现了一个 MvcRouteHandler的东东, 名字感觉跟MVC有点关系了, 那进去瞧瞧?

    public class MvcRouteHandler : IRouteHandler
    {
        // Fields
        private IControllerFactory _controllerFactory;
    
        // Methods
        public MvcRouteHandler();
        public MvcRouteHandler(IControllerFactory controllerFactory);
        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext);
        protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext);
        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext);
    }

    这个GetHttpHandler里面, 有让人激动的东东哦, 先看一下吧, 不继续讲解了

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

    2. 这里为啥defaults和 constraints 都存成 CreateRouteValueDictionary 类型呢, 这里暂时只看一下他存放到哪里吧.

    private static RouteValueDictionary CreateRouteValueDictionary(object values)
    {
        IDictionary<string, object> dictionary = values as IDictionary<string, object>;
        if (dictionary != null)
        {
            return new RouteValueDictionary(dictionary);
        }
        return new RouteValueDictionary(values);
    }
    public RouteValueDictionary(object values)
    {
        this._dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        this.AddValues(values);
    } 

    从这里看, defaults, constraints , DataTokens 都是相同的类型.

    等后面要用的时候, 再去解析吧. 

    这一篇算是与MVC挂上钩了, 下一篇就正式进入MVC环节的解析.

     目录已同步

  • 相关阅读:
    iphoneX适配
    是时候啃一啃http跟https了
    使用阿里巴巴矢量图标库的图标
    react使用高阶组件进行界面跳转
    js性能提升之函数的防抖和节流
    vuex的一些需要知道的点
    react项目之使用猪齿鱼框架---dataSet的基础使用
    从js下手提升代码性能
    vue+ts搭建工程
    学习笔记之TypeScript语法一
  • 原文地址:https://www.cnblogs.com/elvinle/p/6276986.html
Copyright © 2011-2022 走看看