First, why the need for routing priority
We all know that we have no priority in registering routes in the ASP.net MVC project or Webapi project, when the project is larger, has multiple zones, or multiple Web projects, or is developed with a plug-in framework, our route registration is probably not written in one file, Instead, they are scattered across a number of different projects, so that the priority of the routing problem is highlighted.
For example: in 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 in the context
. Maproute (
name: "Login",
URL: "Login",
defaults:new {area = "Admin"), Controller = "Account", action = "Logi n ", id = urlparameter.optional},
namespaces:new string[] {" Wenku.Admin.Controllers "}
);
If you register the above generic default route and then register the login route, you will first match the first route that satisfies the condition, that is, the two route registration is invalid.
This problem is caused by the sequence of these two routing registrations, and there is no priority to registering routes in asp.net mvc and webapi, so today we are going to implement this idea ourselves by adding a priority concept when registering a route.
Second, the solution to the idea
1, first analysis of the route registration portal, such as we create a new mvc4.0 project
public class MvcApplication:System.Web.HttpApplication
{
protected void Application_Start ()
{
Arearegistration.registerallareas ();
Webapiconfig.register (globalconfiguration.configuration);
Filterconfig.registerglobalfilters (globalfilters.filters);
Routeconfig.registerroutes (routetable.routes);
}
There are two registered entries for the MVC route:
A. Arearegistration.registerallareas (); Registering area routes
B. routeconfig.registerroutes (routetable.routes); registering project Routes
There is a WEBAPI route registration entry:
Webapiconfig.register (globalconfiguration.configuration); Registering WEBAPI Routing
2, the Registration route processing class analysis
AreaRegistrationContext
RouteCollection
Httproutecollection
When you register a route, these three classes are primarily registered to handle the route.
3. Route priority scheme
A, change the registration entry for the route
b, customize the structure class routepriority and httproutepriority of a route, these two classes have priority this property
C, custom a registrationcontext to register the route, the registered object for the above custom route.
D, after all the routing registrations are completed and then added to RouteCollection and httproutecollection in the order of precedence, it actually takes effect.
Third, the concrete realization
1. Routing definition
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, define the interface of Route registration
Public interface Irouteregister
{
void Register (Registrationcontext context);
3. Define route Registration Context class
public class Registrationcontext {#region mvc list<routepriority> Routes = new list<routepriority
> (); Public routepriority Maproute (string name, String Url,int priority=0) {return maproute (name, URL, (object) NULL/*
Defaults * *, priority); 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); Routepriority Maproute (string name, string URL, string[] namespaces, int priority = 0) {return mapr
Oute (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); Routepriority Maproute (string name, string URL, object defaults, object constraints, string[] namespaces, in
T 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 Bel Onging to the 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 = Def Aults. 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[] Names
Paces,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<string, object>;
if (dictionary!= null) {return new routevaluedictionary (dictionary); Return to New RoutevAluedictionary (values); #endregion #region http public list
4, the route registration processing method to add to the configuration class
public static Configuration registerroutepriority (this Configuration config) {var typessofar = new List<type> (
);
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);
The var context = new Registrationcontext ();
foreach (var type in Typessofar) {var obj = (irouteregister) activator.createinstance (type); Obj.
Register (context); foreach (var route in the context.) Httproutes.orderbydescending (x => x.priority)) GlobalConfiguration.Configuration.Routes.MapHttpRoute (route. Name, route. Routetemplate, route. Defaults, route. Constraints, route.
Handler); foreach (var route in the context.) Routes.orderbydescending (x => x.priority)) RouteTable.Routes.Add (route.
Name, route);
return config; } private static IENUMERABLE<
Assembly> getreferencedassemblies () {var assemblies = buildmanager.getreferencedassemblies ();
foreach (Assembly Assembly in assemblies) yield return Assembly; This is the end of the work, only to modify the original registration entry in the Global.asax.cs file as public class MvcApplication:System.Web.HttpApplication {protected VO
ID Application_Start () {webapiconfig.register (globalconfiguration.configuration);
Filterconfig.registerglobalfilters (globalfilters.filters);
Routeconfig.registerroutes (routetable.routes); Configuration.instance (). Registercomponents (). Registerroutepriority (); Registering custom Routes}} Use only the custom route registration interface Irouteregister that you want to inherit in each project, for example: public class Registration:irouteregister {public void Register (Registrationcontext context) {//Register back-end Admin Login Routing 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); Register back-end Admin page Default routing context. Maproute (Name: "Admin_default", url: "Admin/{controller}/{action}/{id}", defaults:new {area = "Adm In ", Controller =" Home ", action =" Index ", id = urlparameter.optional}, namespaces:new string[] {" Wenku.admin.c
Ontrollers "}, Priority:10); Register Mobile Access Webapi routing context. Maphttproute (Name: "Mobile_api", Routetemplate: "Api/mobile/{controller}/{action}/{id}", Defaults:n
ew {area = "mobile", action = routeparameter.optional, id = routeparameter.optional, NamespaceName = new string[] {"Wenku.Mobile.Http"}}, constraints:new {action = new startwithcons
Traint ()}, priority:0);
}
}
Iv. Summary
When you encounter a large project registration route does not take effect you should think that there may be the reason for the routing order, the above is the entire content of this article, I hope that the study of everyone to inspire.