zoukankan      html  css  js  c++  java
  • .NET UrlRouting原理

    UrlRouting路由流程:

    添加路由:可以通过调用MapRoute()、MapPageRoute(),它们内部都是创建Route对象,最终添加到RouteCollection中。

        还可以使用[Route("/home/index")]的方式添加,注册路由时需要执行RouteConfig.RegisterRoutes(RouteTable.Routes);

        或者直接调用RouteCollection.Add()方法注册路由

    匹配路由:调用RouteCollection的GetRouteData(),最终调用Route中的GetRouteData(),如果返回非null,则匹配

    排除路由:IgnoreRoute(),也是往RouteCollection中添加了一个Route对象,Route中的handler是StopRoutingHandler。在路由配置时,如果匹配到的路由的Handler是StopRoutingHandler,请求中断

    说明:

    MapRoute()是添加MVC路由,MapPageRoute()是添加WebForm路由。它们的RouteHandler不同,MVC的是MVCRouteHandler,WebForm的是PageRouteHandler

    MVCRouteHandler内部可以获取到IHttpHandler,实现类是MVCHander,它的PR方法中创建Controller,并调用Action

    PageRouteHandler同上,它的IHttpHandler的实现类是Page,Page中有几个事件,我们可以在事件回调中做操作。

    MVC和WebForm都是用的ASP.NET框架,从路由开始有了差别,一个创建Controller,一个创建Page。

    自定义Route:

    可以自定义做一些限制等操作,比如限制域名

        /// <summary>
        /// 支持泛域名的UrlRouting
        /// </summary>
        public class DomainRoute : RouteBase
        {
            #region 变量
            private string _domainName;
            private string _physicalFile;
            private string _routeUrl;
            private bool _checkPhysicalUrlAccess = false;
            private RouteValueDictionary _defaults;
            private RouteValueDictionary _constraints;
            private IList<PathSegment> _pathSegmentLists = new List<PathSegment>();
            private const string REPLACE_PATTEN = @"([w,%]+)";
            private readonly Regex _patten = new Regex(@"{([a-z,A-Z,0-9]+)}", RegexOptions.Compiled);
            private int _segmentCount = 0;
            #endregion
    
            #region 构造函数
            /// <summary>
            /// 
            /// </summary>
            /// <param name="domainName">泛域名</param>
            /// <param name="routeUrl">Url路由</param>
            /// <param name="physicalFile">映射的物理文件</param>
            /// <param name="checkPhysicalUrlAccess">一个值,该值指示 ASP.NET 是否应验证用户是否有权访问物理 URL(始终会检查路由 URL)。此参数设置 System.Web.Routing.PageRouteHandler.CheckPhysicalUrlAccess</param>
            /// <param name="defaults">路由的默认值。</param>
            /// <param name="constraints">一些约束,URL 请求必须满足这些约束才能作为此路由处理。</param>
    
            public DomainRoute(string domainName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)
            {
                this._domainName = domainName.ToLower();
                this._routeUrl = routeUrl;
                this._physicalFile = physicalFile;
                this._checkPhysicalUrlAccess = checkPhysicalUrlAccess;
                this._defaults = defaults;
                this._constraints = constraints;
    
                IList<string> lists = SplitUrlToPathSegmentStrings(routeUrl);
                if (lists != null && lists.Count > 0)
                {
                    this._segmentCount = lists.Count;
                    for (int i = 0; i < lists.Count; i++)
                    {
                        string strPatten = lists[i];
                        if (!string.IsNullOrWhiteSpace(strPatten) && this._patten.IsMatch(strPatten))
                        {
                            PathSegment segment = new PathSegment();
                            segment.Index = i;
    
                            Match match;
                            List<string> valueNames = new List<string>();
                            for (match = this._patten.Match(strPatten); match.Success; match = match.NextMatch())
                            {
                                strPatten = strPatten.Replace(match.Groups[0].Value, REPLACE_PATTEN);
                                valueNames.Add(match.Groups[1].Value);
                            }
                            segment.ValueNames = valueNames.ToArray();
                            segment.Regex = new Regex(strPatten, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                            this._pathSegmentLists.Add(segment);
                        }
                    }
                }
            }
    
            public DomainRoute(string domainName, string routeUrl, string physicalFile)
                : this(domainName, routeUrl, physicalFile, false, new RouteValueDictionary(), new RouteValueDictionary())
            {
    
            }
            #endregion
    
            #region 属性
            /// <summary>
            /// 泛域名
            /// </summary>
            public string DomainName
            {
                get { return this._domainName; }
                set { this._domainName = value; }
            }
            /// <summary>
            /// 映射的物理文件
            /// </summary>
            public string PhysicalFile
            {
                get { return this._physicalFile; }
                set { this._physicalFile = value; }
            }
            /// <summary>
            /// Url路由
            /// </summary>
            public string RouteUrl
            {
                get { return this._routeUrl; }
                set { this._routeUrl = value; }
            }
            #endregion
    
            #region 方法
            [DebuggerStepThrough]
            public override RouteData GetRouteData(HttpContextBase httpContext)
            {
                RouteData result = null;
                HttpRequestBase request = httpContext.Request;
                if (request.Url.Host.ToLower().Contains(this._domainName))
                {
                    string virtualPath = request.AppRelativeCurrentExecutionFilePath.Substring(2) + request.PathInfo;
                    IList<string> segmentUrl = SplitUrlToPathSegmentStrings(virtualPath);
                    if (segmentUrl.Count == this._segmentCount)
                    {
                        PathSegment pathSegment = null;
                        string path = null;
                        bool isOK = true;
                        for (int i = 0; i < this._pathSegmentLists.Count; i++)
                        {
                            pathSegment = this._pathSegmentLists[i];
                            path = segmentUrl[pathSegment.Index];
                            if (!pathSegment.Regex.IsMatch(path))
                            {
                                isOK = false;
                                break;
                            }
                        }
                        if (isOK)
                        {
                            result = new RouteData(this, new PageRouteHandler(this._physicalFile, this._checkPhysicalUrlAccess));
                            result.Values.Add("Domain", this._domainName);
                            Match match = null;
                            for (int i = 0; i < this._pathSegmentLists.Count; i++)
                            {
                                pathSegment = this._pathSegmentLists[i];
                                path = segmentUrl[pathSegment.Index];
                                match = pathSegment.Regex.Match(path);
                                if (pathSegment.ValueNames.Length + 1 == match.Groups.Count)
                                {
                                    for (int j = 0; j < pathSegment.ValueNames.Length; j++)
                                    {
                                        result.Values.Add(pathSegment.ValueNames[j], match.Groups[j + 1].Value);
                                    }
                                }
                            }
                        }
                    }
                    segmentUrl.Clear();
                    segmentUrl = null;
                }
                return result;
            }
    
            public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
            {
                return new VirtualPathData(this, this._physicalFile);
            }
    
            private static IList<string> SplitUrlToPathSegmentStrings(string url)
            {
                List<string> list = new List<string>();
                if (!string.IsNullOrEmpty(url))
                {
                    int index;
                    for (int i = 0; i < url.Length; i = index + 1)
                    {
                        index = url.IndexOf('/', i);
                        if (index == -1)
                        {
                            string str = url.Substring(i);
                            if (str.Length > 0)
                            {
                                list.Add(str);
                            }
                            return list;
                        }
                        string item = url.Substring(i, index - i);
                        if (item.Length > 0)
                        {
                            list.Add(item);
                        }
                        //list.Add("/");
                    }
                }
                list.TrimExcess();
                return list;
            }
            #endregion
    
            #region 内部类
            private class PathSegment
            {
                public int Index { get; set; }
                public Regex Regex { get; set; }
                public string[] ValueNames { get; set; }
            }
            #endregion
        }

    添加路由:

     RouteTable.Routes.Add(new DomainRoute(urlRoutingSetting.DomainName, urlRoutingSetting.RouteUrl, urlRoutingSetting.PhysicalFile, urlRoutingSetting.CheckPhysicalUrlAccess, urlRoutingSetting.Defaults, constraints)); 

  • 相关阅读:
    Windows下安装使用OpenLDAP
    LDAP安装配置(windows)
    LDAP概念和原理介绍
    JDK自带的keytool证书工具详解
    递归算法讲解
    Creating an archive from a directory without the directory name being added to the archive
    Overview of the M&A Process
    Make sure base method gets called in C#
    How to delete specific nodes from an XElement?
    如何学习数据结构?
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12078975.html
Copyright © 2011-2022 走看看