ASP. NET Web API navigation
ASP. First lesson--Getting Started http://www.cnblogs.com/aehyok/p/3432158.html
ASP. The second lesson--crud operation Http://www.cnblogs.com/aehyok/p/3434578.html
ASP. NET Web API lesson three ——. NET client invoke Web API http://www.cnblogs.com/aehyok/p/3439698.html
ASP. Fourth lesson--httpclient Message Processor http://www.cnblogs.com/aehyok/p/3442277.html
ASP. Fifth lesson--web API Routing Http://www.cnblogs.com/aehyok/p/3442051.html
Objective
This article describes how the ASP. NET WEB API routes an HTTP request to a specific action on the controller. A general overview of routing can be found in the previous tutorial http://www.cnblogs.com/aehyok/p/3442051.html. This article focuses on learning the details of the routing process. If you create a Web API project and find that some requests are not routed the way you expect, hopefully this article will help you.
This paper is mainly divided into three stages:
1. Match the URI to a route Template.
2. Select a controller.
3. Select an action.
You can replace some parts of the process with your own custom behavior. In this article, I'll describe the default behavior in the future. At the end of the article, I'll indicate where I can customize the behavior.
Route Templates
The routing template looks similar to a URI path, but it can have placeholders and is indicated by curly braces:
"Api/{controller}/public/{category}/{id}"
When creating a route, you can provide default values for some or all of the placeholders:
defaults:new {category = "all"}
You can also provide a constraint that restricts how the URI fragment matches the placeholder:
constraints:new {id = @ "\d+"} //Only matches if "id" are one or more digits.
The above statement restricts the value of the fragment by a regular expression, which indicates that the ID fragment matches only one or more digits, so the ID fragment in the URI must be a number to match the route.
This framework attempts to match the fragment in the URI path to this template. The text in the template must match exactly. A placeholder can match any value unless you specify a constraint. This framework does not match the other part of the URI, such as a host name or a query string. This framework selects the first matching route in the routing table.
There are two special placeholders: "{controller}" and "{action}".
- "{Controller}" provides the controller name.
- ' {action} ' provides an action name. In the Web API, the usual convention is to ignore "{action}".
Defaults (default value)
If you provide a default value, the route will match the URI that is missing these fragments. For example:
Routes. Maphttproute ( name: "Defaultapi", routetemplate: "Api/{controller}/{category}", defaults:new { Category = "All"});
This URI "Http://localhost/api/products" is matched to this route. The "{category}" fragment is assigned the default value "all".
Route Dictionary (Routing dictionary)
If the framework finds a matching URI, it creates a dictionary containing each placeholder value. This key value is a placeholder name without curly braces. This value is taken from the URI path or from the default value. This field is present in the Ihttproutedata object. This special "{controller}" and "{action}" placeholder are treated the same as other placeholders during the match routing phase. They are simply stored in a dictionary with a different value.
You can use a special routeparameter.optional value in the default value. If a placeholder is given this value, the value will not be added to the routing dictionary, for example:
Routes. Maphttproute ( name: "Defaultapi", routetemplate: "Api/{controller}/{category}/{id}", defaults:new { Category = "All", id = routeparameter.optional});
For the URI path "Api/products", the routing dictionary will contain: controller: "Products", Category: "All".
However, for "api/products/toys/123", the routing dictionary will contain: controller: "Products", Category: "Toys", ID: "123".
This default value can also contain values that do not appear in the route template. If this route matches, the value is stored in the routing dictionary. For example:
Routes. Maphttproute ( name: "Root", routetemplate: "Api/root/{id}", defaults:new {controller = "Customers", id = Routeparameter.optional});
If the URI path is "Api/root/8", the dictionary will contain two values: Controller: "Customers", ID: "8".
Selecting a Controller
Controller selection is handled by the Ihttpcontrollerselector.selectcontroller method. This method takes the httprequestmessage instance as a parameter and returns the httpcontrollerdescriptor.
Its default implementation is provided by the Defaulthttpcontrollerselector class. This class uses a straightforward algorithm:
1. Find the "controller" key for the routing dictionary.
2. Obtain the value of this key and attach the string "controller" to get the type name of the controller.
3. Find the Web API controller with this type name.
For example, if the key-value pair in the routing dictionary is "controller" = "Products", then the controller type is "ProductsController". If there is no matching type, or if there are multiple matches, the framework returns an error to the client.
For step 3,Defaulthttpcontrollerselector uses the ihttpcontrollertyperesolver interface to obtain a list of Web API controller types. The default implementation of Ihttpcontrollertyperesolver returns all public classes that meet the following criteria:
A: The class that implements Ihttpcontroller .
B: Non-abstract class.
C: Class with name ending with "Controller".
Action Selection
Once the controller is selected, the framework selects the action by calling the ihttpactionselector.selectaction method. This method takes Httpcontrollercontext as the parameter and returns the httpactiondescriptor.
This default implementation is provided by the Apicontrolleractionselector class. In order to select an action, the following areas are found:
1.HTTP method of the request.
2. The "action" placeholder in this routing template.
3. Parameters of the action in the controller.
Before we look at the selection algorithm, we need to understand something about the controller action.
what methods in the controller are seen as "actions"? when an action is selected, the framework only examines the public instance method of the controller. Furthermore, it excludes methods of special names (constructors, events, operators, overloads, and so on), as well as class methods that are integrated from Apicontroller.
HTTP Methods
This framework selects only the actions that match the requested HTTP method, determined as follows:
1. You can specify the HTTP method using annotation properties Acceptverbs, Httpdelete, HttpGet, Httphead, Httpoptions, Httppatch, HttpPost, or httpput.
2. Otherwise, if the controller method name starts with "Get", "Post", "Put", "Delete", "Head", "Options", or "Patch", then according to this Convention, the action will support the corresponding HTTP method.
3. If none of the above is true, then this method will support post.
Parameter Bindings.
Parameter binding refers to how the Web API creates parameter values. The following are the default rules for parameter bindings: 1. The simple type is taken from the URI. 2. The complex type is taken from the request body.
The simple type includes all. NET Framework simple type, plus, DateTime, Decimal, Guid, String, and TimeSpan. For each action, at most one parameter can read the request body.
It can also override this default binding rule. See WebAPI Parameter binding under the hood.
In this context, the action selection algorithm is as follows:
1. Create a list of all actions in the controller that match the HTTP request method.
2. If the routing dictionary has an "action" entry, remove the action that does not match the entry value.
3. An attempt was made to match the action parameter to the URI as follows:
A: For each action, get a simple type of argument list, which is where the URI parameter is bound to get. The list does not include optional parameters.
B: From this list, try to find the matching of each parameter in the routing dictionary or in the URI query string. Matches are case-insensitive and are independent of the order of the parameters.
C: Select such an action, and each parameter in the list has a match in the URI.
D: If there are more than one action to satisfy these conditions, choose one with the most parameters.
4. Ignore actions labeled with [nonaction] annotation attributes.
The 3rd step may be confusing. The basic idea is that you can get parameter values from a URI, or a request body, or a custom binding. For parameters from URIs, we want to make sure that the URI actually contains a value for this parameter in its path (through the routing dictionary) or in the query string.
For example, consider the following actions:
public void Get (int id)
Its ID parameter is bound to the URI. Therefore, this action can only match the URI that contains the "id" value in the routing dictionary or query string.
Optional parameters are an exception because they are optional. For optional parameters, it is not related if the binding cannot get its value through a URI.
A complex type is an exception to another cause. A complex type can only be bound to a URI by a custom binding. But in this case, the framework cannot know in advance whether this parameter is bound to a special URI. To find out, this framework needs to invoke this binding. The purpose of the selection algorithm is to select an action based on a static description before invoking the binding. Therefore, the complex type is outside the matching algorithm.
After the action is selected, all parameter bindings are called.
Summary:
1. The action must match the HTTP method of the request.
2. The action name must match the "action" entry in the routing dictionary, if any.
3. For each parameter of the action, if the argument is taken from the URI, the parameter name must be found in the routing dictionary or URI query string. (except for optional parameters and complex types).
4. Attempt to match the maximum number of parameters. The best match may be a parameterless method.
Extended Example
Look at the following routes:
Routes. Maphttproute ( name: "Apiroot", routetemplate: "Api/root/{id}", defaults:new {controller = "products", ID = routeparameter.optional}); Routes. Maphttproute ( name: "Defaultapi", routetemplate: "Api/{controller}/{id}", defaults:new {id = Routeparameter.optional});
Look at the following contoller:
public class Productscontroller:apicontroller {public ienumerable<product> GetAll () {} public Product GETBYID (int id, double Version = 1.0) {} [httpget] public void Findproductsbyname (string name) {} public void Post (product value) {} public void Put (int id, product value) {}}
HTTP request:
Http://localhost:34701/api/products/1?version=1.5&details=1
Route matching:
The URI matches the route named "Defaultapi". The routing dictionary contains the following entries: Controller: "Products", ID: "1". The routing dictionary does not contain query string parameters "version" and "Details", but these will be considered during the action selection.
Controller selection:
The controller type is ProductsController, depending on the "controller" entry in the routing dictionary.
Action selection:
This HTTP request is a GET request. The controller actions that support get are getall, GetById, Findproductsbyname. This routing dictionary does not contain an "action" entry, so there is no need to match the action name.
Next, you will try to match the parameter names of these actions, and only the get action is examined.
Note that the version parameter of the GetById is not considered, because it is an optional parameter.
The GetAll method is very well matched. The GetById method also matches, because the routing dictionary contains "id". The findproductsbyname method does not match.
The GetById method is the winner because it matches a parameter, and GetAll has no arguments. The method is called with the following parameter values: id=1,version=1.5
Note that although version is not used for the selection algorithm, the parameter value is taken from the URI query string.
Extension Points
The Web API provides extensibility points for some parts of the routing process.
To provide your own implementation for any of these interfaces, you can use the Services collection of the httpconfiguration object:
var config = globalconfiguration.configuration;config. Services.replace (typeof (Ihttpcontrollerselector), new Mycontrollerselector (config));
Summarize
This article is very difficult to understand, helpless under more check a bit, it is sure that someone has translated, it is really in the blog park there, I did not find it before? http://www.cnblogs.com/r01cn/archive/2012/12/04/2801158.html , feel the great God translation sincere praise, good to see understand, in order to improve their level of reading English, read a sentence of English, read a translation, and then repeat the word again. This article down really tired. However, I also have a new understanding of the routing mechanism of ASP.
Refer to the original link http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
ASP. 2 Sixth lesson--web API Routing and action selection