Asp. Net Web API 2 Lesson 6-Web API routing and action selection, asp. netapi

Source: Internet
Author: User

Asp. Net Web API 2 Lesson 6-Web API routing and action selection, asp. netapi

Asp. Net Web API navigation

Asp. Net Web API Lesson 1-getting started with http://www.cnblogs.com/aehyok/p/3432158.html

Asp. Net Web API Lesson 2-CRUD operation http://www.cnblogs.com/aehyok/p/3434578.html

Asp. Net Web API third course --. NET client call Web API http://www.cnblogs.com/aehyok/p/3439698.html

Asp. Net Web API Lesson 4 -- HttpClient message processor http://www.cnblogs.com/aehyok/p/3442277.html

Asp. Net Web API Fifth Course -- Web API routing http://www.cnblogs.com/aehyok/p/3442051.html

Preface

This article describes how ASP. NET Web APIs route an HTTP request to a specific Action of the controller. For an overview of routing, see the previous tutorial http://www.cnblogs.com/aehyok/p/3442051.html. This article mainly describes the details of the routing process. If you create a Web API project and find that some requests are not routed as expected, I hope this article will help you.

This article is divided into three phases:

1. Match the URI to a Route Template.

2. Select a Controller.

3. Select an Action.

You can replace some parts of this process with your own custom behavior. In this article, I will describe the default behavior in the future. At the end of the article, I will indicate where the behavior can be customized.

 


Route Templates

The routing template looks similar to a URI path, but it can have placeholders and is indicated by curly brackets:

"api/{controller}/public/{category}/{id}"

When creating a route, you can provide default values for some or all placeholders:

defaults: new { category = "all" }

You can also provide constraints to restrict how URI fragments match placeholders:

constraints: new { id = @"\d+" }   // Only matches if "id" is one or more digits.

The preceding statement limits the value of a segment through a regular expression. The preceding comment indicates that the id segment matches only one or more numbers, therefore, the id segment in the URI must be a number to match the route.

 

This framework tries to match the fragments in the URI path with this template. The text in the template must be strictly matched. A placeholder can match any value unless you specify a constraint. This framework does not match other parts of the URI, such as the host name or a query string. This framework selects the first matched route in the routing table.

There are two special placeholders: "{controller}" and "{action }".

  • "{Controller}" provides the controller name.
  • "{Action}" provides the action name. In Web APIs, the Common Convention ignores "{action.
Defaults (default)

If you provide the default value, the route matches the URI that lacks these fragments. For example:

routes.MapHttpRoute (
    name: "DefaultApi",
    routeTemplate: "api / {controller} / {category}",
    defaults: new {category = "all"}
);
This URI "http: // localhost / api / products" matches this route. The "{category}" segment was assigned the default value "all".

Route Dictionary
If the framework finds a matching URI, it will create a dictionary containing each placeholder value. This key value is a placeholder name without curly brackets. This value is taken from the URI path or the default value. This field is stored in the IHttpRouteData object. During the matching routing phase, the special "{controller}" and "{action}" placeholders are handled the same as other placeholders. They are simply stored in the dictionary with additional values.

In the default value, a special RouteParameter.Optional value can be used. If a placeholder is assigned this value, then this 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 routing template. If this route matches, the value will be stored in the routing dictionary. E.g:

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 HttpControllerDescriptor.

The default implementation is provided by the DefaultHttpControllerSelector class. This class uses a very straightforward algorithm:

1. Find the "controller" key of the routing dictionary.

2. Get the value of this key and append the character string "Controller" to get the type name of the controller.

3. Use this type name to find the Web API controller.

For example, if the key-value pair in the routing dictionary is "controller" = "products", then the controller type is "ProductsController". If there is no match type, or there are multiple matches, the framework will return 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 will return all public classes that meet the following conditions:

a: Class that implements IHttpController.

b: It is a non-abstract class.

c: The class whose name ends with "Controller".

Action Selection

After selecting the controller, the framework will select the action by calling the IHttpActionSelector.SelectAction method. This method takes HttpControllerContext as a parameter and returns HttpActionDescriptor.

This default implementation is provided by the ApiControllerActionSelector class. In order to choose an action, the following aspects are searched:

1. HTTP request method.

2. The "action" placeholder in this routing template.

3. The parameters of the action in the controller.

Before looking for a selection algorithm, we need to understand some things about controller actions.

Which methods in the controller are regarded as "actions"? When selecting an action, this framework only examines the controller's public instance method. Moreover, it will exclude methods with special names (constructors, events, operators, overloads, etc.), as well as class methods integrated from ApiController.

 

HTTP Methods

This framework will only select actions that match the HTTP method of the request, determined as follows:

1. You can use the annotation attributes AcceptVerbs, HttpDelete, HttpGet, HttpHead, HttpOptions, HttpPatch, HttpPost, or HttpPut to specify HTTP methods.

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, then this method will support Post.

Parameter Bindings.

Parameter binding refers to how Web API creates parameter values. The following are the default rules for parameter binding: 1. Simple types are taken from URI. 2. The complex type is taken from the request body.

Simple types include all ".NET framework simple types", in addition, DateTime, Decimal, Guid, String and TimeSpan. For each action, at most only 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 this controller that match the HTTP request method.

2. If the routing dictionary has an "action" entry, remove the action that does not match the value of the entry.

3. Try to match the action parameter with the URI as follows:

A: For each action, get a simple type parameter list, this is where the binding gets the URI parameter. The list does not include optional parameters.

B: From this list, try to find a match for each parameter in the routing dictionary or in the URI query string. The matching is not related to capitalization and to the order of parameters.

C: Select such an action, each parameter in the list has a match in the URI.

D: If there is more than one action that satisfies these conditions, select the one with the most parameter matches.

4. Ignore actions marked with [NonAction] annotation attribute.

 

Step 3 may be confusing. The basic idea is that the parameter value can be obtained from the URI, or the 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 (via the routing dictionary) or 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 URIs that contain an "id" value in the routing dictionary or query string.

Optional parameters are an exception because they are optional. For optional parameters, it does not matter if the binding cannot obtain its value via the URI.

Complex types are an exception for another reason. A complex type can only be bound to a URI through custom binding. But in this case, the framework cannot know in advance whether this parameter is bound to a special URI. In order to find out the situation, the framework needs to call this binding. The purpose of the selection algorithm is to select an action based on the static description before calling the binding. Therefore, complex types are 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 parameter is taken from the URI, the parameter name must be found in the routing dictionary or URI query string. (Except optional parameters and complex types).

4. Try to match the maximum number of parameters. The best match may be a parameterless method.

Extended Example

Look at the following route:

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 content under 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:

This 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 action selection.

Controller selection:

According to the "controller" entry in the routing dictionary, the controller type is ProductsController.

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 "action" entries, so there is no need to match the action name.

In the next step, we will try to match the parameter names of these actions, and only check the GET action.

Note that the version parameter of GetById is not considered because it is an optional parameter.

The GetAll method matches very well. 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 one parameter, and GetAll has no parameters. The method will be called with the following parameter values: id = 1, version = 1.5

Note that although version is not used to select the algorithm, the value of this parameter is taken from the URI query string.

Extension Points

 Web API provides extension points for certain parts of the routing process.

To provide your own implementation for any of the above interfaces, you can use the Services collection of the HttpConfiguration object:

var config = GlobalConfiguration.Configuration;
config.Services.Replace (typeof (IHttpControllerSelector), new MyControllerSelector (config));
totalKnot

 This article is very difficult to understand. I checked it out in desperation. I felt that someone had already translated it. It was really in the blog garden. I did n’t find it before. Http://www.cnblogs.com/ r01cn / archive / 2012/12/04 / 2801158.html, I feel that the translation of the Great God is really good, and I understand it well. In order to improve my level of reading English, read a sentence of English, read a sentence of translation, and then type by word. Again. I'm really tired after this article. However, I have a new understanding of the Asp.Net MVC routing mechanism, which is good.

Refer to the original link http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection

 

Reference page:

http://www.yuanjiaocheng.net/mvc/mvc-helper-htmlstring.html

http://www.yuanjiaocheng.net/CSharp/csharp-array.html

http://www.yuanjiaocheng.net/CSharp/Csharp-keys.html

http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-delete.html

http://www.yuanjiaocheng.net/webapi/config-webapi.html

http://www.yuanjiaocheng.net/CSharp/Csharp-Generics.html

http://www.yuanjiaocheng.net/CSharp/Csharp-sortedlist.html

http://www.yuanjiaocheng.net/ASPNET-CORE/core-razor-layout.html

http://www.yuanjiaocheng.net/webapi/httpclient-consume-webapi.html

http://www.yuanjiaocheng.net/CSharp/Csharp-Generics-collection.html

http://www.yuanjiaocheng.net/mvc/htmlhelper-validationmessage.html

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.