1.为什么需要路由优先级?大家都知道我们在Asp.NetMVC项目或者WebApi项目中注册路由是没有优先级的。当项目比较大,或者有多个区域开发,或者多个web项目,或者使用插件框架的时候,我们的路由注册很可能不会写在一个文件中,而是分散在很多不同项目的文件中。这样一来,路由的优先级问题就凸显出来了。例如:routes.MapRoute(name:"Default",url:"{controller}/{action}/{id}"inApp_Start/RouteConfig.cs,defaults:new{controller="Home",action="Index",id=UrlParameter.Optional});在Areas/Admin/AdminAreaRegistration.cscontext.MapRoute(name:"Login",url:"login",defaults:new{area="Admin",controller="Account",action="Login",id=UrlParameter.可选},namespaces:newstring[]{"Wenku.Admin.Controllers"});如果先注册上面的通用默认路由,再注册登录路由,那么无论怎样,都会先匹配符合条件的第一条路由,即第二条路由注册无效。出现这个问题的原因是这两个路由的注册顺序,而Asp.NetMVC和WebApi中注册路由没有优先级的概念,所以今天我们就来自己实现这个思路,在注册的时候加上一个优先级路线的概念。二、解决方案1、首先分析路由注册的入口。比如我们新建一个mvc4.0项目(RouteTable.Routes);}}Mvc路由有两个注册入口:AreaRegistration.RegisterAllAreas();注册区域路由b.RouteConfig.RegisterRoutes(RouteTable.Routes);注册项路由WebApi路由注册入口有一个:WebApiConfig.Register(GlobalConfiguration.Configuration);注册WebApi路由二、注册路由的处理类分析AreaRegistrationContextRouteCollectionHttpRouteCollection在注册路由时,这三个类主要用于注册和处理路由。3.路由优先级方案a.改变路由的注册入口b.自定义一个路由结构类RoutePriority和HttpRoutePriority。这两个类具有Priority属性c。自定义一个RegistrationContext来注册路由。注册的对象就是上面的自定义路由。d.所有路由注册完成后,会按照优先生效的顺序添加到RouteCollection和HttpRouteCollection中。#p#三、具体实现1、路径由确定publicclassRoutePriority:Route{publicstringName{get;set;}publicintPriority{get;set;}publicRoutePriority(stringurl,IRouteHandlerrouteHandler):base(url,routeHandler){}}publicclassHttpRoutePriority{publicstringName{get;set;}publicintPriority{get;set;}publicstringRouteTemplate{get;set;}publicobjectDefaults{get;set;}publicobjectConstraints{get;set;}publicHttpMessageHandlerHandler{get;set;}}2、确定由注册的接口publicinterfaceIRouteRegister{voidRegister(RegistrationContextcontext);}3、由注册上文类publicclassRegistrationContext{#regionmvcpublicListRoutes=newList();publicRoutePriorityMapRoute(stringname,stringurl,intpriority=0){returnMapRoute(name,url,(object)null/*defaults*/,priority);}publicRoutePriorityMapRoute(stringname,stringurl,objectdefaults,intpriority=0){returnMapRoute(name,url,defaults,(object)null/*constraints*/,priority);}publicRoutePriorityMapRoute(stringname,stringurl,objectdefaults,objectconstraints,intpriority=0){returnMapRoute(name,url,defaults,constraints,null/*namespaces*/,priority);}publicRoutePriorityMapRoute(stringname,stringurl,string[]namespaces,intpriority=0){returnMapRoute(name,url,(object)null/*defaults*/,namespaces,priority);}publicRoutePriorityMapRoute(stringname,stringurl,objectdefaults,string[]namespaces,intpriority=0){returnMapRoute(name,url,defaults,null/*constraints*/,namespaces,priority);}publicRoutePriorityMapRoute(stringname,stringurl,objectdefaults,objectconstraints,string[]namespaces,intpriority=0){varroute=MapPriorityRoute(name,url,defaults,constraints,namespaces,priority);varareaName=GetAreaName(defaults);路线.DataTokens["area"]=areaName;//disablingthenamespacelookupfallbackmechanismkeepsthisareasfromaccidentallypicking//controllersbelongingtootherareasbooluseNamespaceFallback=(namespaces==null||namespaces.Length==0);route.DataTokens["UseNamespaceFallback"]=useNamespaceFallback;返回路由e;}privatestaticstringGetAreaName(objectdefaults){if(defaults!=null){varproperty=defaults.GetType().GetProperty("area");if(property!=null)return(string)property.GetValue(defaults,null);}returnnull;}privateRoutePriorityMapPriorityRoute(stringname,stringurl,objectdefaults,objectconstraints,string[]namespaces,intpriority){if(url==null){thrownewArgumentNullException("url");}varroute=newRoutePriority(url,newMvcRouteHandler()){Name=name,Priority=优先级,Defaults=CreateRouteValueDictionary(默认),Constraints=CreateRouteValueDictionary(约束),DataTokens=newRouteValueDictionary()};if((namespaces!=null)&&(namespaces.Length>0)){route.DataTokens["Namespaces"]=namespaces;}Routes.Add(route);returnroute;}privatestaticRouteValueDictionaryCreateRouteValueDictionary(objectvalues){vardictionary=valuesasIDictionary;if(dictionary!=null){returnnewRouteValueDictionary(dictionary);}returnnewRouteValueDictionary(值);}#endregion#regionhttppublicListHttpRoutes=newList();publicHttpRoutePriorityMapHttpRoute(stringname,stringrouteTemplate,intpriority=0){returnMapHttpRoute(name,routeTemplate,defaults:null,constraints:null,handler,priority:priority);}publicHttpRoutePriorityMapHttpRoute(stringname,stringrouteTemplate,objectdefaults,intpriority=0){returnMapHttpRoute(name,routeTemplate,defaults,constraints:null,handler:null,priority:priority);}publicHttpRoutePriorityMapHttpRoute(stringname,stringrouteTemplate,objectdefaults,objectconstraints,intpriority=0){returnMapHttpRoute(name,routeTemplate,defaults,constraints,handler:null,priority:priority);}publicHttpRoutePriorityMapHttpRoute(stringname,stringrouteTemplate,objectdefaults,objectconstraints,HttpMessageHandlerhandler,intpriority=0){varhttpRoute=newHttpRoute();httpRoute.Name=名称;httpRoute.RouteTemplate=routeTemplate;httpRoute.Defaults=defaults;httpRoute.Constraints=constraints;httpRoute.Handler=handler;httpRoute.Priority=priority;HttpRoutes.Add(httpRoute);returnhttpRoute;}#endregion}4、把路由登记处理方法添加到Configuration类中publicstaticConfigurationRegister(thisRouteConfigurationRegister)){vartypesSoFar=newList();varassemblies=GetReferencedAssemblies();foreach(Assemblyassemblyinassemblies){vartypes=assembly.GetTypes().Where(t=>typeof(IRouteRegister).IsAssignableFrom(t)&&!t.IsAbstract&&!t.IsInterface);typesSoFar.AddRange(types);}varcontext=newRegistrationContext();foreach(vartypeintypesSoFar){varobj=(IRouteRegister)Activator.CreateInstance(type);obj.Register(context);}foreach(varrouteincontext.HttpRoutes.OrderByDescending(x=>x.Priority))GlobalConfiguration.Configuration.Routes.MapHttpRoute(route.Name,route.RouteTemplate,route.Defaults,route.Constraints,route.Handler);foreach(varrouteincontext.Routes.OrderByDescending(x=>x.Priority))RouteTable.Routes.Add(route.Name,route);returnconfig;}privatestaticIEnumerableGetReferencedAssemblies(){varassemblies=BuildManager.GetReferencedAssemblies();foreach(Assemblyassemblyinassemblies)yieldreturnassembly;}这样就大功告成了,你只需要使用它在全球。修改asax.cs文件中原来的注册入口为publicclassMvcApplication:System.Web.HttpApplication{protectedvoidApplication_Start(){WebApiConfig.Register(GlobalConfiguration.Configuration);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);RouteConfig.RegisterRoutes(RouteTable.Routes).Instance().RegisterComponents().RegisterRoutePriority();//注册一个自定义路由}}在每个项目中使用只需要继承自定义路由注册接口IRouteRegister,例如:publicclassRegistration:IRouteRegister{publicvoidRegister(RegistrationContextcontext){//注册后端管理登录路由context.MapRoute(name:"Admin_Login",url:"Admin/login",defaults:new{area="Admin",controller="Account",action="登录",id=UrlParameter.Optional},namespaces:newstring[]{"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:newstring[]{"Wenku.Admin.Controllers"},priority:10);//注册移动端访问WebApi路由上下文.MapHttpRoute(name:"Mobile_Api",routeTemplate:"api/mobile/{controller}/{action}/{id}",defaults:new{area="mobile",action=RouteParameter.Optional,id=RouteParameter.Optional,namespaceName=newstring[]{"Wenku.Mobile.Http"}},constraints:new{action=newStartWithConstraint()},priority:0);}}4.总结这是一个针对Asp.NetMvc的应用A小功能扩展,小项目可能不需要这个功能,但是有时候项目太大,注册的路由没有生效的时候,你应该想到可能是路由顺序的问题,这时候路由优先级功能有可能给您带来便利e.总之,分享给有需要的朋友参考。