千家信息网

如何为ASP.NET MVC及WebApi添加路由优先级

发表于:2025-11-18 作者:千家信息网编辑
千家信息网最后更新 2025年11月18日,本篇内容介绍了"如何为ASP.NET MVC及WebApi添加路由优先级"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅
千家信息网最后更新 2025年11月18日如何为ASP.NET MVC及WebApi添加路由优先级

本篇内容介绍了"如何为ASP.NET MVC及WebApi添加路由优先级"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、为什么需要路由优先级

大家都知道我们在Asp.Net MVC项目或WebApi项目中注册路由是没有优先级的,当项目比较大、或有多个区域、或多个Web项目、或采用插件式框架开发时,我们的路由注册很可能 不是写在一个文件中的,而是分散在很多不同项目的文件中,这样一来,路由的优先级的问题就突显出来了。

比如: App_Start/RouteConfig.cs中

routes.MapRoute(   name: "Default",   url: "{controller}/{action}/{id}",   defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );  Areas/Admin/AdminAreaRegistration.cs中  context.MapRoute(   name: "Login",    url: "login",   defaults: new { area = "Admin", controller = "Account", action = "Login", id = UrlParameter.Optional },   namespaces: new string[] { "Wenku.Admin.Controllers" } );

假如是先注册上面那个通用的default路由,再注册这个login的路由,那么无论怎么样,都会先匹配第一个满足条件的路由,也就是第两个路由注册是无效的。
造成这个问题的原因就是这两个路由注册的顺序问题,而Asp.Net MVC及WebApi中注册路由都没有优先级这个概念,所以今天我们就是要自己实现这个想法,在注册路由时加入一个优先级的概念。

二、解决思路

1、先分析路由注册的入口,比如我们新建一个mvc4.0的项目

public class MvcApplication : System.Web.HttpApplication {   protected void Application_Start()   {     AreaRegistration.RegisterAllAreas();      WebApiConfig.Register(GlobalConfiguration.Configuration);     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);     RouteConfig.RegisterRoutes(RouteTable.Routes);   } }

Mvc路由的注册入口有两个:
a. AreaRegistration.RegisterAllAreas(); 注册区域路由
b. RouteConfig.RegisterRoutes(RouteTable.Routes); 注册项目路由

WebApi路由注册入口有一个:
WebApiConfig.Register(GlobalConfiguration.Configuration); 注册WebApi路由

2、注册路由的处理类分析

AreaRegistrationContext
RouteCollection
HttpRouteCollection

注册路由时主要是由这三个类来注册处理路由的。

3、路由优先级方案

a、更改路由的注册入口
b、自定义一个路由的结构类RoutePriority及HttpRoutePriority,这两个类下面都有Priority这个属性
c、自定一个RegistrationContext来注册路由,注册的对象为上述自定义路由。
d、所有的路由注册完成之后再按优先顺序添加到RouteCollection及HttpRouteCollection中实际生效。

三、具体实现

1、路由定义

public class RoutePriority : Route {   public string Name { get; set; }   public int Priority { get; set; }    public RoutePriority(string url, IRouteHandler routeHandler)     : base(url,routeHandler)   {    } }  public class HttpRoutePriority {   public string Name { get; set; }   public int Priority { get; set; }   public string RouteTemplate{get;set;}   public object Defaults{get;set;}   public object Constraints{get;set;}   public HttpMessageHandler Handler{get;set;} }

2、定义路由注册的接口

public interface IRouteRegister {   void Register(RegistrationContext context); }

3、定义路由注册上下文类

public class RegistrationContext {   #region mvc   public List Routes = new List();    public RoutePriority MapRoute(string name, string url,int priority=0)   {     return MapRoute(name, url, (object)null /* defaults */, priority);   }    public RoutePriority MapRoute(string name, string url, object defaults, int priority = 0)   {     return MapRoute(name, url, defaults, (object)null /* constraints */, priority);   }    public RoutePriority MapRoute(string name, string url, object defaults, object constraints, int priority = 0)   {     return MapRoute(name, url, defaults, constraints, null /* namespaces */, priority);   }    public RoutePriority MapRoute(string name, string url, string[] namespaces, int priority = 0)   {     return MapRoute(name, url, (object)null /* defaults */, namespaces, priority);   }    public RoutePriority MapRoute(string name, string url, object defaults, string[] namespaces,int priority=0)   {     return MapRoute(name, url, defaults, null /* constraints */, namespaces, priority);   }    public RoutePriority MapRoute(string name, string url, object defaults, object constraints, string[] namespaces, int priority = 0)   {     var route = MapPriorityRoute(name, url, defaults, constraints, namespaces, priority);     var areaName = GetAreaName(defaults);     route.DataTokens["area"] = areaName;      // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up     // controllers belonging to other areas     bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);     route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;      return route;   }    private static string GetAreaName(object defaults)   {     if (defaults != null)     {       var property = defaults.GetType().GetProperty("area");       if (property != null)         return (string)property.GetValue(defaults, null);     }      return null;   }    private RoutePriority MapPriorityRoute(string name, string url, object defaults, object constraints, string[] namespaces,int priority)   {     if (url == null)     {       throw new ArgumentNullException("url");     }      var route = new RoutePriority(url, new MvcRouteHandler())     {       Name = name,       Priority = priority,       Defaults = CreateRouteValueDictionary(defaults),       Constraints = CreateRouteValueDictionary(constraints),       DataTokens = new RouteValueDictionary()     };      if ((namespaces != null) && (namespaces.Length > 0))     {       route.DataTokens["Namespaces"] = namespaces;     }      Routes.Add(route);     return route;   }    private static RouteValueDictionary CreateRouteValueDictionary(object values)   {     var dictionary = values as IDictionary;     if (dictionary != null)     {       return new RouteValueDictionary(dictionary);     }      return new RouteValueDictionary(values);   }   #endregion    #region http   public List HttpRoutes = new List();    public HttpRoutePriority MapHttpRoute(string name, string routeTemplate, int priority = 0)   {     return MapHttpRoute(name, routeTemplate, defaults: null, constraints: null, handler: null, priority: priority);   }    public HttpRoutePriority MapHttpRoute(string name, string routeTemplate, object defaults, int priority = 0)   {     return MapHttpRoute(name, routeTemplate, defaults, constraints: null, handler: null, priority: priority);   }    public HttpRoutePriority MapHttpRoute(string name, string routeTemplate, object defaults, object constraints, int priority = 0)   {     return MapHttpRoute(name, routeTemplate, defaults, constraints, handler: null, priority: priority);   }    public HttpRoutePriority MapHttpRoute(string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler, int priority = 0)   {     var httpRoute = new HttpRoutePriority();     httpRoute.Name = name;     httpRoute.RouteTemplate = routeTemplate;     httpRoute.Defaults = defaults;     httpRoute.Constraints = constraints;     httpRoute.Handler = handler;     httpRoute.Priority = priority;     HttpRoutes.Add(httpRoute);      return httpRoute;   }   #endregion }

4、把路由注册处理方法添加到Configuration类中

public static Configuration RegisterRoutePriority(this Configuration config) {   var typesSoFar = new List();   var assemblies = GetReferencedAssemblies();   foreach (Assembly assembly in assemblies)   {     var types = assembly.GetTypes().Where(t => typeof(IRouteRegister).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface);     typesSoFar.AddRange(types);   }    var context = new RegistrationContext();   foreach (var type in typesSoFar)   {     var obj = (IRouteRegister)Activator.CreateInstance(type);     obj.Register(context);   }    foreach (var route in context.HttpRoutes.OrderByDescending(x => x.Priority))     GlobalConfiguration.Configuration.Routes.MapHttpRoute(route.Name, route.RouteTemplate, route.Defaults, route.Constraints, route.Handler);    foreach (var route in context.Routes.OrderByDescending(x => x.Priority))     RouteTable.Routes.Add(route.Name, route);    return config; }  private static IEnumerable GetReferencedAssemblies() {   var assemblies = BuildManager.GetReferencedAssemblies();   foreach (Assembly assembly in assemblies)     yield return assembly; } 这样一来就大功告成,使用时只需要在Global.asax.cs文件中修改原注册入口为public class MvcApplication : System.Web.HttpApplication {   protected void Application_Start()   {     WebApiConfig.Register(GlobalConfiguration.Configuration);     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);     RouteConfig.RegisterRoutes(RouteTable.Routes);      Configuration.Instance()       .RegisterComponents()       .RegisterRoutePriority(); //注册自定义路由   } } 在每个项目中使用只需要要继承自定义路由注册接口IRouteRegister,例如:public class Registration : IRouteRegister {   public void Register(RegistrationContext context)   {     //注册后端管理登录路由     context.MapRoute(      name: "Admin_Login",      url: "Admin/login",      defaults: new { area = "Admin", controller = "Account", action = "Login", id = UrlParameter.Optional },      namespaces: new string[] { "Wenku.Admin.Controllers" },      priority: 11    );      //注册后端管理页面默认路由     context.MapRoute(       name: "Admin_default",       url: "Admin/{controller}/{action}/{id}",       defaults: new { area = "Admin", controller = "Home", action = "Index", id = UrlParameter.Optional },       namespaces: new string[] { "Wenku.Admin.Controllers" },       priority: 10     );      //注册手机访问WebApi路由     context.MapHttpRoute(       name: "Mobile_Api",       routeTemplate: "api/mobile/{controller}/{action}/{id}",       defaults: new       {         area = "mobile",         action = RouteParameter.Optional,         id = RouteParameter.Optional,         namespaceName = new string[] { "Wenku.Mobile.Http" }       },       constraints: new { action = new StartWithConstraint() },       priority: 0     );   } }

"如何为ASP.NET MVC及WebApi添加路由优先级"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

路由 优先级 项目 入口 两个 文件 问题 处理 这样一来 一来 内容 区域 多个 实际 就是 接口 更多 概念 知识 顺序 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 宁波便携式工控机服务器 数据库为什么会置疑 软件开发阶段有 下列关于软件开发的描述正确的是 服务业软件开发税率 中国中医药数据库官网 数据库简单设计说明书 混合软件开发前景怎么样 网站上传到服务器如何访问 常用的社交软件开发 csgo韩国服务器维护中 学习大数据软件开发 中小学生网络安全教育微视频 网络安全宣传恶意软件要防范 科技互联网技术 上海品牌软件开发定制平均价格 服务器对外开放文件怎么调 女生考数据库工程师好不好 软件开发合作方案模板 河南汉维网络技术有限公司 电脑微信网络安全掉线怎么办 调查版数据库标准 社区网络安全讲座信息 宁波便携式工控机服务器 关于维护网络安全正确的说法是 必虎共享网络安全吗 武汉大学网络安全学院推免生名单 云服务器支持的工程运营管理软件 查找access数据库 网络数据库试卷及答案
0