Add route priority to ASP. NET MVC and Webapi

Source: Internet
Author: User

First, why need routing priority

We all know that we have no priority in registering routes in an ASP. NET MVC project or Webapi project, and when a project is larger, or has multiple regions, or multiple Web projects, or is developed with a plug-in framework, our route registrations are probably not written in a single file. Instead, the problem of routing priorities is highlighted by the spread of files in many different projects.

For example: in App_start/routeconfig.cs

Routes. MapRoute (    name: "Default",    URL: "{controller}/{action}/{id}",    defaults:new {controller = "Home", action = "Index", id = urlparameter.optional});

In Areas/admin/adminarearegistration.cs

Context. MapRoute (    name: "Login",    
URL: "Login", defaults:new {area = "Admin", controller = "Account", action = "Login", id = urlparameter.optional},< C7/>namespaces:new string[] {"Wenku.Admin.Controllers"});

If it is to register the above generic default route, and then register the login route, then no matter what, will first match the first one to satisfy the condition of the route, that is, the two route registration is invalid.
This is caused by the order of the two route registrations, and the notion that registered routes in ASP. NET MVC and Webapi do not have a priority, so today we are going to implement this idea by adding a priority concept when registering a route.

Second, the solution of ideas

1, first analyze the entrance of the route registration, for example, 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 registry entries for MVC routes:
A. Arearegistration.registerallareas (); Registering zone routes
B. routeconfig.registerroutes (routetable.routes); Registering Project Routes

The WEBAPI route registration entry has one:
Webapiconfig.register (globalconfiguration.configuration); Registering WEBAPI routes

2. Processing class analysis of registered route
AreaRegistrationContext
RouteCollection
Httproutecollection

When you register a route, it is primarily the three classes that register the processing route.

3. Route priority scheme
A. Change the registration entry for a route
b, customize the structure of a route class routepriority and Httproutepriority, these two classes have the priority attribute below
C, custom a registrationcontext to register the route, the registered object is the above custom route.
D, all routes are registered and then added in order of precedence to routecollection and httproutecollection to actually take effect.

Third, the concrete realization

1. Route 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 the route registration

public interface irouteregister{    void Register (Registrationcontext context);

3. Defining the routing Registration Context class

public class registrationcontext{#region MVC public list<routepriority> Routes = new List<routepriority&gt    ;(); 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);        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); } 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 B Elonging 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[] Namespa        Ces,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 new RouteValueDictionary (values);    } #endregion #region http public list

4. Add the route registration processing method 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);    } 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<assEmbly> getreferencedassemblies () {var assemblies = buildmanager.getreferencedassemblies (); foreach (Assembly Assembly in assemblies) yield return Assembly;}

In this way, you only need to modify the original registered entry in the Global.asax.cs file to

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 (); Register custom Route    }}

In each project, you use only the irouteregister that you want to inherit from the custom route registration interface, for example:

public class registration:irouteregister{public void register (Registrationcontext context) {//Registered backend management login route 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 the backend Admin page by default route 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); Register the phone to access the WEBAPI routing context.            Maphttproute (Name: "Mobile_api", Routetemplate: "Api/mobile/{controller}/{action}/{id}", defaults:new {area = "mobile", action= routeparameter.optional, id = routeparameter.optional, namespacename = new string[] {"Wen Ku.        Mobile.http "}}, constraints:new {action = new Startwithconstraint ()}, priority:0    ); }}

Iv. Summary

This is a small feature of ASP. NET MVC, small projects may not need this feature, but sometimes when the project is large, the registered route does not take effect when you should think that it is possible because of the routing order, the function of this route priority will be able to bring you convenience. In short, share to the friends who need reference.

Add route priority to ASP. NET MVC and Webapi

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.