管道处理模型三

六.MVC路由扩展

路由扩展的三个层面

1.在MapRoute层面扩展:

Routes.MapRoute("TestStatic","Test/{action}",new {controller="Second"})

只是添加url规则,HttpHandler根本就没有替换到。

2.在Route层面扩展:

先建立一个自己的route,MyRoute,这里要继承RouteBase:

    /// <summary>
    /// 直接扩展route,拒绝浏览器
    /// </summary>
    public class MyRoute : RouteBase
    {
        /// <summary>
        /// 解析路由信息
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            //如果是 Chrome浏览器 62.0.3202.94版本 ,则访问 Pipe/Refuse,此页面上只有一句话“<h2>拒绝chrome浏览器访问</h2>”,而其他浏览器不作限制
            if (httpContext.Request.UserAgent.IndexOf("Chrome/62.0.3202.94") >= 0)
            {
                RouteData rd = new RouteData(this, new MvcRouteHandler());
                rd.Values.Add("controller", "Pipe");
                rd.Values.Add("action", "Refuse");
                return rd;
            }
            return null;
        }


        /// <summary>
        /// 指定处理的虚拟路径
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return null;
        }
    }

然后add到RouteCollection中去。

   public class RouteConfig
    {
        public static void RegisterMyRoutes(RouteCollection routes)
        {
            routes.Add(new MyRoute());
        }

        public static void RegisterMyMVCHandler(RouteCollection routes)
        {
            routes.Add(new Route("Eleven/{*Info}", new ElevenRouteHandler()
                ));
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//忽略路由
                                                             //routes.IgnoreRoute("test/{*pathInfo}");
                                                             //mvc路由规则下的扩展
            routes.IgnoreRoute("Handler/{*pathInfo}");
           
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] { "Ruanmou.MVC5.Controllers" }
            );
           
        }
    }

注意,这里没有用routes.MapRoute方法,直接用add,为什么可以这样用,还是看MapRoute方法:


自定义的路由也要在global注册

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();//注册区域路由
            GlobalConfiguration.Configure(WebApiConfig.Register);//注册webapi路由
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//

            RouteConfig.RegisterMyMVCHandler(RouteTable.Routes);
            RouteConfig.RegisterMyRoutes(RouteTable.Routes);
            RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());//替换默认的控制器工厂
        }

好了,运行一下吧


从图上可以看到,因为在route上扩展了新的路由规则,遇到chrome浏览器就跳到refuse页面,达到了拒绝chrome浏览器的效果,但对于其他浏览器还正常显示。

针对移动端、PC端用哪个控制器,中文、英文环境用哪个控制器,用户登录了跳到哪里去,没登录跳到哪里去,就可以在route层面上扩展,可以随意定义规则,因为能拿到context,有了上下文就有了全世界。

3.扩展Handler,不一定是MvcHandler

    /// <summary>
    /// 扩展IRouteHandler,
    /// 扩展IHttpHandler
    /// </summary>
    public class ElevenRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new ElevenHttpHandler(requestContext);
        }
    }

    /// <summary>
    /// 还是我们熟悉的handler
    /// </summary>
    public class ElevenHttpHandler : IHttpHandler
    {
        public ElevenHttpHandler(RequestContext requestContext)
        {
            Console.WriteLine("构造ElevenHandler");
        }

        public void ProcessRequest(HttpContext context)
        {
            string url = context.Request.Url.AbsoluteUri;
            context.Response.Write(string.Format("这里是Eleven定制:{0}", this.GetType().Name));
            context.Response.Write((string.Format("当前地址为:{0}", url)));

            context.Response.End();
        }

        public virtual bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

RouteConfig.cs:

    /// <summary>
    /// 路由配置
    /// </summary>
    public class RouteConfig
    {
        public static void RegisterMyRoutes(RouteCollection routes)
        {
            routes.Add(new MyRoute());
        }

        public static void RegisterMyMVCHandler(RouteCollection routes)
        {
            routes.Add(new Route("Eleven/{*Info}", new ElevenRouteHandler()));
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//忽略路由
                                                             //routes.IgnoreRoute("test/{*pathInfo}");
                                                             //mvc路由规则下的扩展
            routes.IgnoreRoute("Handler/{*pathInfo}");
           
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] { "Ruanmou.MVC5.Controllers" }
            );
           
        }
    }

然后在global中注册:

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();//注册区域路由
            GlobalConfiguration.Configure(WebApiConfig.Register);//注册webapi路由
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//

            RouteConfig.RegisterMyMVCHandler(RouteTable.Routes);
            RouteConfig.RegisterMyRoutes(RouteTable.Routes);
            RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());//替换默认的控制器工厂
        }

运行一下,


为什么可以做到呢?


所以上面的流程就是,先建立一个RegisterMyMVCHandler的路由规则,指定它的RouteHandler为ElevenRouteHandler,然后通过ElevenRouteHandler又找到了ElevenHttpHandler,而ElevenHttpHandler里面的功能就是打印了两句话。

到了这个层面后,在例子中我们只是打印了两句话,但是可以做的扩展就多了,可以在ProcessRequest方法中版权申明,或者做一些留后门的事情,获取dll文件,获取webconfig信息,甚至得到数据库数据,想干嘛就干嘛。(好恐怖)

猜你喜欢

转载自blog.csdn.net/cainong2005/article/details/80211218
今日推荐