First, the introduction of the route
ASP. NET Web API routing is the gateway to the entire API. We access a resource through a route map to find the URL of the corresponding resource. Gets the resource through the URL.
For an internal implementation of the ASP. NET Web API, our request will eventually be anchored to a specific action. So, ASP. NET Web API routing is the process of mapping client requests to the corresponding action.
Two-way route mode 2.1 template Routing
Template routing is the default route provided by the ASP. Let's briefly explain the usage of this middle-road.
Default Template Routing
A route template needs to be defined before template routing is used. The following default routing template:
Using system.web.http;namespace supernova.webapi{public static class Webapiconfig {public static void Register (httpconfiguration config) { //Web API Configuration and service //Web API Routing config. Maphttpattributeroutes (); Config. Routes.maphttproute ( name: "Defaultapi", routetemplate: "Api/{controller}/{id}", defaults:new {id = Routeparameter.optional} );}}}
This template route is created by default for new projects under the App_start folder.
We can see that the URL format for this template is Api/{controller}/{id}. The API representative takes the API directory in front of the resource, and the controller represents the director name of the requested resource. The ID represents an optional Id,id for a resource. This default template is non-action, so it is a request to differentiate the resource, we must add the request mode attribute on the action to differentiate.
1. We add a test controller API.
public class Testcontroller:apicontroller {Public Object Get1 () { return "D1"; } }
Debug with Fiddldr as follows:
2. We add two methods as follows:
public class Testcontroller:apicontroller {Public Object Get1 () { return "D1"; } public Object Get2 () { return ' D2 '; } }
We re-debug with fiddler as follows:
The error message is:
{"Message": "Error occurred. "," Exceptionmessage ":" Found multiple actions matching the request: \ r \ n type Supernova.Webapi.Controllers.TestController get1\r\n type Supernova.Webapi.Controllers.TestController Get2 "," Exceptiontype ":" System.InvalidOperationException "," StackTrace ":" In System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction ( Httpcontrollercontext controllercontext) \ r \ n System.Web.Http.ApiController.ExecuteAsync (httpcontrollercontext ControllerContext, CancellationToken cancellationtoken) \ r \ n in System.Web.Http.Dispatcher.HttpControllerDispatcher. <sendasync>d__1.movenext () "}
We will change the code to read as follows:
public class Testcontroller:apicontroller {Public Object Get1 () { return "D1"; } [HttpPost] public Object Get2 () { return ' D2 '; } }
Debug returns information for Get1.
from the above two Tests we can draw the following conclusions:
- The default request method for action is httpget.
- When multiple actions are requested in the same way, under the default route template (no action), multiple operations will be matched.
- Based on the above two conclusions, the default route template does not meet a variety of operations (such as modification operations, which may be modified for different fields) for a single request to a resource.
Customizing Template Routing
We re-customize the template routing as follows:
Using system.web.http;namespace supernova.webapi{public static class Webapiconfig {public static void Register (httpconfiguration config) { //Web API Configuration and service //Web API Routing config. Maphttpattributeroutes (); Config. Routes.maphttproute ( name: "Defaultapi", routetemplate: "Api/{controller}/{action}/{id}", defaults: New {id = routeparameter.optional} );}}}
From the above we can see that on the basis of the default route, our team routing template adds a level action.
The test API is as follows:
public class Testcontroller:apicontroller {Public Object Get1 () { return "D1"; } public Object Get2 () { return ' D2 '; } }
We're going to go through http://192.168.0.230/api/test again, return 404,
We access through HTTP://192.168.0.230/API/TEST/GET1, the results are correct,
We access through Http://192.168.0.230/api/test/Get2, the results are correct,
by customizing the routing template We can draw the following conclusions:
- By adding the action directory to the routing template, the location of the resource directly acts on the action.
- Multiple HttpGet methods can coexist in a controller.
- Based on the above two conclusions, it is possible to modify the routing template to satisfy a variety of operations for a resource request mode.
2.2 Feature Routing
Attribute routing defines a routing rule by attribute the action.
Sometimes we have this requirement, and one of the resources we requested has child resources. For example, the article reviews the resources associated with this relationship. We would like to get all the comments under an article via the following URL: api/book/id/comments. This routing pattern is difficult to implement simply by using template routing. This is where we need the feature routing to solve the problem. The ASP. NET Web API prepares us for the route feature, which can be directly hit on the action and is very flexible and intuitive to use.
I'll start with a brief introduction to how feature routing is used.
We redefine the API as follows:
public class Testcontroller:apicontroller { [Route ("Demo")] [HttpGet] public object Get1 () { return "D1"; } [Route ("Demo/get")] [HttpGet] public Object Get2 () { return ' D2 '; } }
We can see that the action was tagged.
Use Fiddler to debug as follows:
The URL of the request Get1 is Http://192.168.0.230/demo
The URL of the request Get2 is Http://192.168.0.230/demo/get
2.3 Comparison of two routes
- Template routing is very convenient for simple business, but a little less for complex resource operations.
- Attribute routing can be modified flexibly without changing the name of the action.
- Attribute routing can create friendly URLs for associated resources.
- Attribute routing can be used to constrain the routing parameters and to fine-tune the control.
Iii. feature Routing details 3.1 using the route feature
Using feature routing is simple and requires no additional configuration, just a route tag on the action. This will automatically invalidate the template route.
As follows:
public class Testcontroller:apicontroller { [Route ("Demo")] [HttpGet] public object Get1 () { return "D1"; } [Route ("Demo/get")] [HttpGet] public Object Get2 () { return ' D2 '; } }
3.2 Using the Routeprefix feature
Sometimes we want to add a uniform prefix to all operations on a resource.
The first way:
public class Testcontroller:apicontroller { [Route ("Api/demo")] [HttpGet] public object Get1 () { return "D1"; } [Route ("Api/demo/get")] [HttpGet] public Object Get2 () { return ' D2 '; } }
This way it seems to be a little bit retarded. Then we can use Routeprefix to add the feature to the controller, then the request for the resource will be added to the API directory.
The second method:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("Demo")] [HttpGet] public object Get1 () { return "D1"; } [Route ("Demo/get")] [HttpGet] public Object Get2 () { return ' D2 '; } }
3.3 Overriding the prefix rule for an action
The method in 3.2 allows you to prefix a resource with the preceding unification. Then the question comes, if we will have such a demand, I have a resource of most of the requests need to prefix, but there are so one or two resources do not need to prefix, swollen? In fact, Microsoft has already thought to us, others said, of course, allow you to rewrite the action prefix ah.
The following code, we re-Get1:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("~/demo")] [HttpGet] public object Get1 () { return "D1"; } [Route ("Demo/get")] [HttpGet] public Object Get2 () { return ' D2 '; } }
Debug with fiddler as follows:
Error, the correct URL is actually: Http://192.168.0.230/demo
3.4.1 Routing parameter constraints
Now the problem again, so many requests, especially the GET request method, all need to take parameters ah, how to define the type of parameters, length range and other constraints?
The answer is that parameter variables in the route can be constrained by the "{parameter variable name: constraint}".
The built-in constraints for ASP. NET Web API include:
{X:ALPHA} constraint-Case English letter
{X:bool}
{X:datetime}
{X:decimal}
{x:double}
{X:float}
{X:guid}
{X:int}
{x:length (6)}
{x:length (1,20)} constraint length range
{X:long}
{x:maxlength (10)}
{x:min (10)}
{X:range (10,50)}
{X:regex (regular expression)}
The following code:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route (' Demo/{id:int}]] [httpget] public object Get1 ( { return "D1"; } [Route ("Demo/{name}")] [HttpGet] public Object Get2 () { return ' D2 '; } }
Above, if the fragment variable ID is of type int, it is routed to the first action Get1, if not, to the second action Get2.
Use Fiddler to debug as follows:
The request is Get1.
The request is Get2.
You can set multiple constraints for one parameter variable at the same time:
The following code:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("Demo/{id:int:min (5)}")] [HttpGet] public Object Get1 () { return "D1"; } [Route ("Demo/{name}")] [HttpGet] public Object Get2 () { return ' D2 '; } }
Request URL:HTTP://192.168.0.230/API/DEMO/1 Navigate to Get2
3.4.2 Extended route parameter constraints
Implement the Ihttprouteconstraint interface to customize constraint rules. Implement a constraint that cannot be 0.
The code is as follows:
public class Nonzeroconstraint:ihttprouteconstraint {public bool Match (Httprequestmessage request, Ihttproute route, String parametername, idictionary<string, object> values, httproutedirection Routedirection) { object value; if (values. TryGetValue (parametername, out value) && value! = null) { long longvalue; If (value is long) { Longvalue = (long) value; return longvalue! = 0; } String valuestring = convert.tostring (value, cultureinfo.invariantculture); if (Int64.tryparse (valuestring, Numberstyles.integer, CultureInfo.InvariantCulture, out Longvalue)) { return Longvalue! = 0; } } return false; }
Register a custom constraint in Webapiconfig in the App_start folder. The original template route must be commented
public static class Webapiconfig {public static void Register (httpconfiguration config) { //Web API Configuration and service //Web API routing //config. Maphttpattributeroutes (); Config. Routes.maphttproute ( // name: "Defaultapi", // routetemplate: "Api/{controller}/{action}/{id}" , // defaults:new {id = routeparameter.optional}// ); var constraintresolver = new Defaultinlineconstraintresolver (); CONSTRAINTRESOLVER.CONSTRAINTMAP.ADD ("Nonzero", typeof (Nonzeroconstraint)); Config. Maphttpattributeroutes (Constraintresolver); } }
The test code is as follows:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route (' Demo/{id:nonzero} ')] [HttpGet] public Object Get1 () { return "D1"; } [Route ("Demo/{name}")] [HttpGet] public Object Get2 () { return ' D2 '; } }
Use url:http://192.168.0.230/api/demo/0 to navigate to Get2
3.5 Optional parameters and their default values
Sometimes, the parameters we request are optional, what to do, we need to set the parameters of the default value to be processed.
The code is as follows:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("Demo/{id:int}")] [HttpGet] public object Get1 (int id=1) { return "D1" +ID; } [Route ("Demo/{name}")] [HttpGet] public Object Get2 () { return ' D2 '; } }
Get1 is positioned when the parameter does not exist or is of type int, and Get2 is positioned when the argument exists that is not int.
Url:http://192.168.0.230/api/demo positioning Get1
URL:HTTP://192.168.0.230/API/DEMO/2 positioning Get1
URL:HTTP://192.168.0.230/API/DEMO/ABC positioning Get2
3.6 Setting a name for a route
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("Demo/{id:int}", name= "get content by id")] [HttpGet] public object Get1 (int id = 1) { return "D1" + ID; } [Route ("Demo/{name}")] [HttpGet] public Object Get2 () { return ' D2 '; } }
3.7 Route Priority order
Route precedence is determined by the custom and Routeorder properties of the route attribute settings.
The Convention is:
1. Static fragment variables
2. Fragment variables with constraints
3. Fragment variables without constraints
4. A constrained wildcard fragment variable
5. Wildcard Fragment variables without constraints
The default value of the Routeorder property is 0, and the lower the value of the property, the earlier the row.
The test code is as follows, according to the priority level:
[Routeprefix ("API")] public class Testcontroller:apicontroller { [Route ("Orders/detail", Name = "static fragment variable")] [HttpGet] public Object Get1 () { return "Orders/detail"; } [Route ("Orders/{id:int}", Name = "Fragment variable with constraint")] [HttpGet] public object Get2 (int id) { return ' orders/{id:int} '; } [Route ("Orders/{name}", name = "Fragment variable without constraint")] [HttpGet] public Object Get3 (string name) { return ' orders/{name} '; } [Route ("orders/lily", Order = 1)] [HttpGet] public Object Get4 () { return ' orders/lily '; } }
Url:http://192.168.0.230/api/orders/detail locating Get1 static fragment variable order=0
url:http://192.168.0.230/api/orders/lily locating Get3 with constrained fragment variables order=0
URL:HTTP://192.168.0.230/API/ORDERS/1 locating Get2 Non-constrained fragment variables order=0
Get3 contains the definition of GET4, so it can never be defined to GET4. This is where special attention is needed in feature routing.
3.8 Routing Design Specifications
Verbs cannot appear in 1.URL.
Reference:
http://www.eggtwo.com/news/detail/155
Https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
Http://www.cnblogs.com/n-pei/archive/2012/07/17/2595352.html
ASP. NET WEBAPI Routing configuration