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

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.

主站蜘蛛池模板: 水富县| 孝感市| 丰镇市| 木兰县| 莱阳市| 甘孜| 乌恰县| 安乡县| 武强县| 浦城县| 山阳县| 手机| 道孚县| 阿拉善左旗| 景东| 东莞市| 临桂县| 柳林县| 阳原县| 济阳县| 老河口市| 台东县| 和政县| 比如县| 南部县| 司法| 公安县| 禹城市| 富蕴县| 犍为县| 巢湖市| 黎平县| 包头市| 大姚县| 永胜县| 尉犁县| 喀喇| 涞源县| 柘荣县| 留坝县| 县级市|