6.自定义路由

1.路由学习

2.路由源码解读

3.自定义路由

前面学习了这么多,那么我手也有点痒了,那么就来把路由扩展一下,看看到底能做多少事情(到底能做什么?其实我也不知道,毕竟还没在项目中使用过,能带来多大好处,也不是很清楚,虽然知道理论,但是不知道如何把学习的理论价值最大化,其实也是挺可悲的,不说了,干活吧!!!)

既然要扩展路由,那么我们肯定是需要一个路由的,那么如何弄一个路由出来了?前面也说过了,我们需要继承一下路由的基类RouteBase

我们来看看RouteBase的源码:

namespace System.Web.Routing
        {
            [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
            public abstract class RouteBase
            {
                private bool _routeExistingFiles = true;

                public bool RouteExistingFiles
                {
                    get
                    {
                        return this._routeExistingFiles;
                    }
                    set
                    {
                        this._routeExistingFiles = value;
                    }
                }

                public abstract RouteData GetRouteData(HttpContextBase httpContext);

                public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
            }
        }
View Code

我们再来看看框架是如何实现的,Route源码如下:

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

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            BoundUrl boundUrl = this._parsedRoute.Bind(requestContext.RouteData.Values, values, this.Defaults, this.Constraints);
            if (boundUrl == null)
            {
                return null;
            }
            if (!this.ProcessConstraints(requestContext.HttpContext, boundUrl.Values, RouteDirection.UrlGeneration))
            {
                return null;
            }
            VirtualPathData virtualPathData = new VirtualPathData(this, boundUrl.Url);
            if (this.DataTokens != null)
            {
                foreach (KeyValuePair<string, object> current in this.DataTokens)
                {
                    virtualPathData.DataTokens[current.Key] = current.Value;
                }
            }
            return virtualPathData;
        }
View Code

我们仿照框架实现方法,代码如下:

/// <summary>
    /// 自定义路由
    /// </summary>
    public class MyRoute : RouteBase
    {
        /// <summary>
        /// 返回我们定义的路由信息
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            //可以省略此句话(父类默认为true),为true表示应用此路由去处理所有请求(甚至包括与现有文件匹配的请求),为false,那么就不应用此路由
            base.RouteExistingFiles = true;

            // 封装有关路由的信息。(这里我使用MVC自带的对路由请求的处理机制)
            RouteData routeData = new RouteData(this,new MvcRouteHandler());
            //获取存储路由的字典
            RouteValueDictionary dictionary =  routeData.Values;
            //添加自定的路由到字典中
            dictionary.Add("controller", "Home");
            dictionary.Add("action", "Index");
            return routeData;
         }

        /// <summary>
        /// 表示有关路由和虚拟路径的信息,该路由和虚拟路径是在使用 ASP.NET 路由框架生成 URL 时产生的。
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return null;
        }
    }

注意:

  1.这里面有一个HttpContextBase参数,我在上面没有并没有使用,但是并不代表没用,其实用处非常大,例如:检查ip,浏览器类型,参数等等

  2.因为我们还是使用MVC自带的处理机制,所以还是会走控制器中的动作,如果我们自定义处理机制,那么就不会走控制器中的动作(可以调试一下),也就不会返回视图

    MVC的是使用虚拟路径来访问的,而我们自己写的其实是请求的物理文件

视图代码如下:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
        <h1>我是Home/Index页面 </h1>
    </div>
</body>
</html>
View Code

url:http://localhost:8955/

其实我们完全可以自定义对路由的处理机制,代码如下:

RouteData routeData = new RouteData(this,new MyRouteHandle());
   /// <summary>
    /// 处理匹配路由模式的请求的协定
    /// </summary>
    public class MyRouteHandle : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new MyHandler();
        }
    }

    /// <summary>
    /// 自定义 HTTP 处理程序同步处理 HTTP Web 请求而实现的协定。
    /// </summary>
    public class MyHandler : IHttpHandler
    {
        /// <summary>
        /// 获取一个值,该值指示其他请求是否可以使用 System.Web.IHttpHandler 实例。
        /// </summary>
        public bool IsReusable => true;

        /// <summary>
        /// 通过实现 System.Web.IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。
        /// </summary>
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentEncoding = Encoding.UTF8;
            context.Response.Write("我是Home/Index页面2");
            context.Response.Write(context.Request.Headers);
        }
    }

 显示效果如下:

url:http://localhost:8955/

原文地址:https://www.cnblogs.com/zjdbk/p/10632347.html