官术网_书友最值得收藏!

Selecting routes from attributes

ASP.NET Core, or rather, the routing middleware, will take the request URL and check for all the routes it knows about, to see whether any match the request. It will do so while respecting the route insertion order, so be aware that your request may accidentally fall into a route that isn't the one you were expecting. Always add the most specific ones first, and then the generic ones.

After a template is found that matches the request, ASP.NET Core will check whether there is an available action method on the target controller that does not have a NonActionAttribute instance that forbids a method to be used as an action, or has an attribute inheriting from HttpMethodAttribute that matches the current HTTP verb. These are listed here:

  • HttpGetAttribute
  • HttpPostAttribute
  • HttpPutAttribute
  • HttpDeleteAttribute
  • HttpOptionsAttribute
  • HttpPatchAttribute
  • HttpHeadAttribute

All of them inherit from HttpMethodAttribute: this is the root class to use for filtering based on the HTTP verb.

If any of these is found, then the route will only be selected if the HTTP verb matches one of the verbs specified. There can be many attributes, meaning the action method will be callable using any of the HTTP verbs specified.

There are other HTTP verbs, but ASP.NET Core only supports these out of the box. If you wish to support others, you need to subclass HttpMethodAttribute and supply your list or use ActionVerbsAttribute. Interestingly, ASP.NET Core—as before in the ASP.NET web API—offers an alternative way of locating an action method: if the action token is not supplied, it will look for an action method whose name matches the current HTTP verb, regardless of the casing.

You can use these attributes to supply different action names, which allows you to use method overloading. For example, if you have two methods with the same name that take different parameters, the only way to differentiate between them is by using different action names:

public class CalculatorController
{
//Calculator/CalculateDirectly
[HttpGet(Name = "CalculateDirectly")]
public IActionResult Calculate(int a, int b) { ... }

//Calculator/CalculateByKey
[HttpGet(Name = "CalculateById")]
public IActionResult Calculate(Guid calculationId) { ... }
}

If that's not possible, then you can use different target HTTP verbs:

//GET Calculator/Calculate
[HttpGet]
public IActionResult Calculate(int a, int b) { ... }

//POST Calculator/Calculate
[HttpPost]
public IActionResult Calculate([FromBody] Calculation calculation) { ... }

Of course, you can limit an action method—or the whole controller—so that it can only be accessed if the request is authenticated by using AuthorizeAttribute. We won't go over that here, as it will be discussed in Chapter 11, Security.

It is worth noting, however, that even if the whole controller is marked with AuthorizeAttribute, individual actions can still be accessible if they bear AllowAnonymousAttribute:

[Authorize]
public class PrivateController
{
[AllowAnonymous]
public IActionResult Backdoor() { ... }
}

Another option is to constrain an action based on the content type of the request. You use ConsumesAttribute for that purpose, and you can apply it as follows:

[HttpPost]
[Consumes("application/json")]
public IActionResult Process(string payload) { ... }
For an explanation of what content types are, please see https://www.w3.org/Protocols/rfc1341/4_Content-Type.html.

Another attribute that contributes to the route selection is RequireHttpsAttribute. If it's present in a method or controller class, a request is only accepted if it comes through HTTPS.

Finally, there are route constraints. These are generally used to validate the tokens passed in the request, but they can be used to validate the request as a whole. We will discuss them shortly.

So, the sequence is as follows:

  1. Find the first template that matches the request.
  2. Check that a valid controller exists.
  3. Check that a valid action method exists in the controller, either by action name or by verb matching.
  1. Check that any constraints present are valid.
  2. Check that any attributes that contribute to the route selection (AuthorizeAttribute, NonActionAttribute, ConsumesAttribute, ActionVerbsAttribute, RequireHttpsAttribute, and HttpMethodAttribute) all are valid.

We will see how constraints can affect route selection shortly.

Using special routes

The following routes are special because they have a particular meaning to ASP.NET Core:

  • [HttpGet("")]: This is the controller's default action; only one can be defined. If applied on a method without required parameters, it will be the default action for the whole app.
  • [HttpGet("~/")]: This is the application's default action for the default controller: it maps to the root of the application (for example, /).

So, if you set [HttpGet("")] on a controller's action method and do not define any other route, then it will be the default action for that controller, and if you set [HttpGet("~/")] with no routing table, then it will be the default action and the default controller.

The next section explains how to restrict a route based on the calling host and/or the server's port.

主站蜘蛛池模板: 繁昌县| 南安市| 鲁山县| 泰州市| 中江县| 澄城县| 裕民县| 鹤庆县| 无极县| 肃南| 万源市| 黄陵县| 济源市| 高碑店市| 灵川县| 沁水县| 大宁县| 常宁市| 郑州市| 随州市| 丘北县| 华蓥市| 秦皇岛市| 汉寿县| 马山县| 阿勒泰市| 河间市| 四平市| 榕江县| 鹤庆县| 河源市| 闽侯县| 丰台区| 富阳市| 中牟县| 岱山县| 通化县| 思南县| 林西县| 沙坪坝区| 溧水县|