六.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;
-
}
-
}
//如果是 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" }
-
);
-
-
}
-
}
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;
-
}
-
}
-
}
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" }
-
);
-
-
}
-
}
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());//替换默认的控制器工厂
-
}
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信息,甚至得到数据库数据,想干嘛就干嘛。(好恐怖)
所以,管道处理模型的核心:多个HttpModule以及HttpHandler对25个固定事件的扩展。