2.2WEBAPI Routing on Action

Source: Internet
Author: User

This article describes how the ASP. NET WEB API routes HTTP requests to specific operations on the controller.

for a high-level overview of routing, see Routing for ASP .

This article looks at the details of the routing process. If you create a Web API project and find some requests not to route the way you expect, hopefully this article will help.

A route has three main phases:

    1. Match the URI to the route template.
    2. Select a controller.
    3. Select an action.

you can replace the process of some parts with your own custom behavior. In this article, I describe the default behavior. Finally, I noticed the place where you can customize the behavior.

Route template

The route template looks similar to a URI path, but it can have placeholder values, denoted by curly braces:

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

When you create a route, you can provide default values for some or all of the placeholders:

You can also provide constraints that limit how the URI segment can match a placeholder:

The framework tries to match the segments in the template's URI path. the text in the template must match exactly. placeholder matches any value, unless you specify a constraint. The framework does not match other parts of the URI, such as host name or query parameters. the framework matches the first route selected in the URI routing table.

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

    • The name of the controller provided by the "{}" controller.
    • The name of the action provided by the action {}. in the Web API, the usual convention is to omit the "action {}".
Default value

If you provide a default value, the route matches the URI, and it is missing these segments. For example:

The "Http://localhost/api/products" URI matches this route. the "{category}" segment assigns the default value "all".

Routing Dictionaries

If the framework finds a matching URI, it creates a dictionary that contains the value for each placeholder. The key is a placeholder name and does not include curly braces. These values are either from the URI path or from the default value. This dictionary is stored in the ihttproutedata object.

in this route matching phase, the special "{}" controller and the "Action {}" placeholder are treated like other placeholders. They are stored only in the dictionary, with other values.

By default, routeparameter.optional can have special value. If the placeholder gets the value specified, the value is not added to the routing dictionary. For example:

For the URI path of the "api/product", the routing dictionary will contain:

    • Controller: "Product"
    • Category: "Everyone"

However, for "api/products/Toys/123", the routing dictionary will contain:

    • Controller: "Product"
    • Category: "Toys"
    • ID: "123"

The default setting can also include a value in the alignment template that does not appear anywhere. If the route matches, the value is stored in the dictionary. For example:

If the URI path is "api/root/8", this dictionary will contain two values:

    • Controller: "Customer"
    • ID: "8"
Select Controller

The controller selection is processed by the Ihttpcontrollerselector.selectcontroller method. This method takes an instance of Httprequestmessage and returns Httpcontrollerdescriptor. The default implementation is provided by the Defaulthttpcontrollerselector class. This class uses a simple algorithm:

    1. Locate in the Routing dictionary Key "controller".
    2. Take the value of this key and append the string "controller" to get the type name of the control.
    3. Look for the Web API controller with this type name.

For example, if the routing dictionary contains a key-value pair "Controller" = "Product", then the type of the controller is "ProductsController". If there are no matching types or multiple matches, the framework returns an error to the client.

Step 3, Defaulthttpcontrollerselector uses the ihttpcontrollertyperesolver interface to get a list of WEB API controller types. the default implementation of Ihttpcontrollertyperesolver returns all public classes (a) execution Ihttpcontroller, (b) is not abstract, and (c) has a name in the " End of the controller.

Select action

After selecting the controller, the framework will select the action by calling the ihttpactionselector.selectaction method. This method takes Httpcontrollercontext and returns httpactiondescriptor.

The default implementation is provided by the Apicontrolleractionselector class. to select an action, it looks like the following:

    • The HTTP method of the request.
    • In the route template, if there is a "action {}" placeholder.
    • The parameters of the operation on the controller.

Before choosing the algorithm, we need to know something about the controller operation.

The method on the controller is considered "action"? When you select an action, the framework simply looks at the public instance method on the controller. In addition, it excludes the "special name" method (constructors, events, operator overloads, and so on), and the Apicontroller class from the inherited method.

HTTP method. The framework selects only the matching requirements and determines the behavior of the following HTTP methods:

    1. You can use the HTTP method specified by the attribute: acceptverbs, httpdelete, public , httphead, httpoptions , httppatch, httppost , or httpput.
    2. Otherwise, if the name of the controller method starts with "Get", "post", "Put", "delete", "header", "option" or "hotfix", then the HTTP method supported by the Convention action.
    3. If none of the above is true, the method supports post.

parameter bindings. parameter binding is the value of how the Web API creates parameters. the default rule for parameter binding is this:

    • The simple type is taken from the URI.
    • A complex type is taken from the request body.

simple types include all the. NET framework primitive types, plus datetime , decimal , Guid, string , and TimeSpan . for each operation, at most one parameter can read the request body.

It is possible to override the default binding rules. See WEBAPI parameter bindings under the hood .

With this background, here is the action selection algorithm.

    1. A list of all operations created on the controller that matches the HTTP request method.
    2. If the routing dictionary has an "action" item, delete the operation whose name does not match this value.
    3. Try to match the URI to the action parameter as follows:
      1. for each operation, get is a simple type that binds a list of parameters from the URI to get the parameter. Optional parameters that are excluded.
      2. from this list, try to find the name that is appropriate for each parameter, or the query string for the routing dictionary or URI. matches are case-sensitive and do not depend on the order of the parameters.
      3. Select each parameter in the list in the URI match operation.
      4. If more of this action meets these criteria, pick one that has the most parameters to match.
    4. Actions that ignore the [infringing] attribute.

Step #3 is the most confusing. Its basic idea is that a parameter can get its value from the URI, from the request body, or from the custom binding. for parameters from URIs, we want to make sure that the URI actually contains the value of the parameter in the path (through the routing dictionary) or in the query string.

For example, consider the following actions:

the URI to which the Id parameter is bound. Therefore, this action can only match a URI that contains the "Social Security Number" value in the routing dictionary or query string.

Optional parameters are an exception because they are optional. as an optional parameter, it is OK if the binding cannot get value from the URI.

complex types are an exception, for different reasons. a complex type can only be bound to a URI by a custom binding. However, in this case, the framework cannot know in advance whether the parameter is bound to a specific URI. in order to find the answer, it will need to call the binding. The target of the selection algorithm is a static description of the action selected before any binding is invoked. Therefore, the complex type is excluded from the matching algorithm.

After you select the operation, all parameter bindings are called.

Summary

    • The action must match the HTTP method of the request.
    • If the current operation name must match the "action" entry in the routing dictionary.
    • for each parameter, if the parameter is from a URI, then the parameter name must be found in the routing dictionary or the URI of the query string. (except for parameters that are optional and complex types.) )
    • try to match the most parameters. the best match may be a method without any parameters.
Examples of extensions

Route

Routes.Maphttproute(Name: "Apiroot",Routetemplate: "Api/root/{id}",Defaults: New {Controller= "Products",Id= Routeparameter.Optional }); . Maphttproute ( Name:  " Defaultapi ", Routetemplate:  "Api/{controller}/{id}" , Defaults: new { ID = Span class= "Typ" >routeparameter. Optional }      

Controller

Public Class ProductsController : Apicontroller{ Public IEnumerable<Product> GetAll() {} Public Product GetById(IntId, DoubleVersion= 1.0) {} [HttpGet] Public void Findproductsbyname (string Name)  {} public void  post (product value< Span class= "pun" >)  {} public  void put ( int Id, product Value)  {} }  

HTTP Request:

GET 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 items:

    • Controller: "Product"
    • ID: "1"

The routing dictionary does not contain query string parameters, "version", and "details", but these are still considered in the action selection.

Controller selection

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

Select action

The HTTP request is a GET request. The controller behavior that supports GET is GetAll , GetById and FindProductsByName . The routing dictionary does not contain an "action" entry, so we do not need a matching action name.

Next, we try to match the operation of the parameter name, only see the action.

Action Matching Parameters
GetAll No one
GetById "" ID
FindProductsByName Name

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

GetAll method to match trivial. GetById method is also matched, because the routing dictionary contains "id". FindProductsByName method does not match.

The GetById method wins because it matches a parameter, with GetAll no parameters. Call the method with the following parameter value:

    • ID = 1
    • version = 1.5

Note that even if the selection algorithm does not use a version , the value of the parameter comes from the URI of the query string.

Extension points

The routing process in some parts of the Web API provides an extensibility point.

To provide your own implementation for any of these interfaces, use the service collection on the httpconfiguration object:

2.2WEBAPI Routing on Action

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.