自定义ASP.NET MVC路由系统截获MVC的路由请求

从之前的文章已经可以看到ASP.NET mvc路由系统的可配置和可扩展优点。如果这些都还没能满足你的要求,那你完全可以自定义ASP.NET MVC 路由系统的行为。下面我分别通过Route Base和Route Handler的方法来说明在ASP.NET MVC中自定义路由的方法。

一、自定义一个RouteBase的实现,截获ASP.NET MVC的请求

如果你不喜欢ASP.NET MVC默认、标准的URL匹配方式,你可以继承类RouteBase重写GetRouteData和GetVirtualPath方法来控制ASP.NET MVC对URL匹配,参数的获取,链接的生成。

RouteBase的两个方法:

GetRouteData(HttpContextBase httpContext):这个方法是用来根据请求的Url的获取路由信息,然后ASP.NET MVC框架会来依次调用所有注册的路由规则(RouteTable.Routes)的每一个节点,直到其中一个返回非空(non- null)值。

GetVirtualPath(RequestContext requestContext, RouteValueDictionary values):这个方法是用来生成链接信息,然后ASP.NET MVC框架会来依次调用所有注册的路由规则(RouteTable.Routes)的每一个节点,直到其中一个返回非空(non- null)值。

为了演示自定义一个RouteBase的场景,我们举一个例子:假如有一个系统已经运行了一段时间了,最近对系统进行了一次升级可能有的页面的URL地址有了变化,但他又要求要原来老的URL地址(/articles/Windows_3.1_Overview.html)能够正常的访问,因为用户可能把原来老的URL地址放到了收藏夹保存了起来,如果因为升级他们原来的URL不能访问了,会带来很多麻烦。

为了满足上面的要求我们需要一个Controller来接受原来老的URL。

 
  1. using System.Web.Mvc;
  2. namespace URLsAndRoutes.Controllers {
  3. public class LegacyController : Controller {
  4. public ActionResult GetLegacyURL(string legacyURL) {
  5. return View((object)legacyURL);
  6. }
  7. }
  8. }
LegacyController对应的视图GetLegacyURL.cshtml:
 
  1. @model string
  2. @{
  3. ViewBag.Title = "GetLegacyURL";
  4. Layout = null;
  5. }
  6. <h2>GetLegacyURL</h2>
  7. The URL requested was: @Model
通过继承类RouteBase,重写方法GetRouteData手动处理老的URL请求:
 
  1. using System;
  2. using System.linq;
  3. using System.Web;
  4. using System.Web.Mvc;
  5. using System.Web.Routing;
  6. namespace URLsAndRoutes.Infrastructure {
  7. public class LegacyRoute : RouteBase {
  8. private string[] urls;
  9. public LegacyRoute(params string[] targetUrls) {
  10. urls = targetUrls;
  11. }
  12. public override RouteData GetRouteData(HttpContextBase httpContext) {
  13. RouteData result = null;
  14. string requestedURL =
  15. httpContext.Request.AppRelativeCurrentExecutionFilePath;
  16. if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase)) {
  17. result = new RouteData(this, new MvcRouteHandler());
  18. result.Values.Add("controller", "Legacy");
  19. result.Values.Add("action", "GetLegacyURL");
  20. result.Values.Add("legacyURL", requestedURL);
  21. }
  22. return result;
  23. }
  24. public override VirtualPathData GetVirtualPath(RequestContext requestContext,
  25. RouteValueDictionary values) {
  26. return null;
  27. }
  28. }
  29. }

上面定义了一个字符串数组来存储老的URL,并通过构造函数来传入这个类能够处理的全部Url,然后在方法GetRouteData内判断当前url是否属于老的URL,如果是就新建一个RouteData实例并给controller和action赋值,也就是把请求定向到LegacyController中的Action,GetLegacyURL,最返回一个RouteData的实例,告诉MVC框架找到对应的RouteData信息,停止往下找匹配的路由结点。如果不是老的URL,就返回null,控制权交给MVC框架,继续往下找匹配的路由结点,直到找到一个返回为非null的RouteData。

最后,注册我们自定义的Route Base到ASP.NET 框架路由系统。

 
  1. public static void RegisterRoutes(RouteCollection routes) {
  2. routes.Add(new LegacyRoute(
  3. "~/articles/Windows_3.1_Overview.html",
  4. "~/old/.NET_1.0_Class_Library"));
  5. routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
  6. new { controller = "Home", action = "Index", id = UrlParameter.Optional });
  7. }

执行结果:

通过利用重写RouteBase,为controller和action变量赋值就可以在ASP.NET MVC中实现以.html结尾的伪静态。具体请看我之前的文章:教你如何在asp.net mvc中实现高性能以html结尾的伪静态

二、自定义一个Route Handler

方法一中在GetRouteData方法中是有下面一行代码:

 
  1. result = new RouteData(this, new MvcRouteHandler());
我们是告诉的MVC框架使用默认的MvcRouteHandler来处理这个请求,MvcRouteHandler是框架自带的Handler,继承了接口IRouteHandler。MvcRouteHandler类是默认的连接mvc的路由系统和controller、action和model桥梁。其实我们除了上面写一个RouteBase的子类来截获ASP.NET MVC的请求,也可以使用接口IRouteHandler,自己实现一个RouteHandler。
 
  1. using System.Web;
  2. using System.Web.Routing;
  3. namespace URLsAndRoutes.Infrastructure {
  4. public class CustomRouteHandler : IRouteHandler {
  5. public IHttpHandler GetHttpHandler(RequestContext requestContext) {
  6. return new CustomHttpHandler();
  7. }
  8. }
  9. public class CustomHttpHandler : IHttpHandler {
  10. public bool IsReusable {
  11. get { return false; }
  12. }
  13. public void ProcessRequest(HttpContext context) {
  14. context.Response.Write("Hello");
  15. }
  16. }
  17. }

上面CustomHttpHandler固定返回一个CustomHttpHandler实例,CustomHttpHandler每次接收到请求都返回一个字符串“Hello”。

最后,告诉MVC框架使用我们自定义的CustomRouteHandler。

 
  1. public static void RegisterRoutes(RouteCollection routes) {
  2. routes.Add(new Route("SayHello", new CustomRouteHandler()));
  3. routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
  4. new { controller = "Home", action = "Index", id = UrlParameter.Optional });
  5. }
执行结果:


三、总结

上面通过简单的实例通过Route Base和Route Handler的方法来说明在ASP.NET MVC中自定义路由的方法,最后都是在注册路由的里面插入了我们写的类,可以达到截获MVC的路由请求,控制路由匹配和请求返回特定内容效果。注意:MVC注册路由是有先后顺序的,所以我们自定义的类是要写在默认路由的前面。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值