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

Using routing attributes

An alternative to adding routes to a routing table is using routing attributes. Routing attributes existed before ASP.NET Core and were even around in ASP.NET MVC and Web API. If we want to have routing attributes automatically recognized by ASP.NET Core, we need to do this:

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

In the following sections, we will learn about a few routing attributes and see how to apply them.

Let's see how we can define routes with attributes.

Defining routes

These attributes are used to define routes and can be composed together; if we add a routing attribute to a class and another to one of its methods, the actual route will result from both of them.

The most obvious use of routing attributes would be to decorate an action method, as follows:

[Route("Home/Index")]
public IActionResult Index() { ... }

If, for example, you have many actions in the same controller and you wish to map them all using the same prefix (Home), you can do the following:

[Route("Home")]
public class HomeController
{
[Route("Index")]
public IActionResult Index() { ... }

[Route("About")]
public IActionResult About() { ... }
}
In previous (non-Core) versions of MVC and Web API, you could use RoutePrefixAttribute for this purpose. Now, RouteAttribute takes care of both cases.

Routes are additive, which means if you specify a route in a controller and then on an action method, you will get both, as in Home/Index or Home/About.

As you can see, the route parameter in the HomeController class matches the conventional name for the controller (Home). Because of this, we can also use the [controller] special token:

[Route("[controller]")]
public class HomeController { ... }

For an API controller, we can use this:

[Route("api/[controller]")]
public class ServicesController { ... }

In addition, each of the actions is mapped with a name that exactly matches the method's name. Likewise, we can use [action]:

[Route("[action]")]
public IActionResult Index() { ... }

[Route("[action]")]
public IActionResult About() { ... }

Multiple route attributes can be passed, so that the action method will respond to different requests:

[Route("[action]")]
[Route("")]
[Route("Default")]
public IActionResult Index() { ... }

The Index method will be callable by any one of the following requests:

/Home
/Home/Index
/Home/Default

Notice that the Home part comes from the route attribute applied at the class level. If, on the other hand, you specify a slash in the template, you make the template absolute; this template will look as follows:

[Route("Default/Index")]
public IActionResult Index() { ... }

This can only be accessed as follows:

/Default/Index

If you want to take the controller into consideration, you should either name it explicitly in the template or use the [controller] special token:

[Route("[controller]/Default/Index")]
public IActionResult Index() { ... }

This will be accessible as follows:

/Home/Default/Index
The [controller] and [action] tokens are for when we want to use constants for routes. These constants have the potential to be used in lots of places, as they are not stuck to specific actions and controllers. They were not available in previous versions of ASP.NET MVC or Web API.

Default routes

With routing attributes, you can specify the default controller by applying RouteAttribute with a blank template:

[Route("")]
public class HomeController { ... }

The default action in a controller will also be the one with an empty template, as follows:

[Route("")]
public IActionResult Index() { ... }

If there is no method with an empty route template, ASP.NET Core will try to find one with a name matching the current HTTP method.

Constraining routes

You can also specify route constraints, and the syntax is identical to what we've seen before:

[Route("Calculate({a:int},{b:int})")]
public IActionResult Calculate(int a, int b) { ... }

Defining areas

You can define routes that include areas too, by applying AreaAttribute to a controller:

[Area("Products")]
[Route("[controller]")
public class ReportingController { ... }

Similar to [controller] and [action], there is also the special [area]token that you can use in your templates to indicate the current area, as inferred from the filesystem:

[Route("[area]/Default")]
public IActionResult Index() { ... }

Specifying action names

You can specify an action name for a controller method, through ActionNameAttribute, as follows:

[ActionName("Default")]
public IActionResult Index() { ... }

You can also do this through any one of the HTTP verb selection attributes (HttpGetAttribute, HttpPostAttribute, HttpPutAttribute, HttpOptionsAttribute, HttpPatchAttribute, HttpDeleteAttribute or HttpHeadAttribute):

[HttpGet(Name = "Default")]
public IActionResult Index() { ... }
Please do remember that you cannot specify a route template and an action name at the same time, as this will result in an exception being thrown at startup time when ASP.NET Core scans the routing attributes. Also, do not specify ActionNameAttribute and a verb selection attribute at the same time as specifying the action name.

Defining non-actions

If you want to prevent a public method in a controller class from being used as an action, you can decorate it with NonActionAttribute:

[NonAction]
public IActionResult Process() { ... }

Restricting routes

When we talked about route constraints, we saw that we can restrict an action method so that it is only callable if one or more the following conditions are met:

  • It matches a given HTTP verb (ActionVerbsAttribute, Http*Attribute).
  • It is called using HTTPS (RequireHttpsAttribute).
  • It is called with a given content type (ConsumesAttribute).

We won't go into this in any further detail, as this has been explained before.

Setting route values

It is possible to supply arbitrary route values in an action method. This is the purpose of the RouteValueAttributeabstract class. You need to inherit from it:

public class CustomRouteValueAttribute : RouteValueAttribute
{
public CustomRouteValueAttribute(string value) : base("custom", value) { }
}

Then, apply and use it as follows:

[CustomRouteValue("foo")]
public IActionResult Index()
{
var foo = this.ControllerContext.RouteData.Values["foo"];
return this.View();
}
AreaAttribute is an example of a class inheriting from RouteValueAttribute. There is no way to pass arbitrary route data tokens through attributes.

As you can see, quite a lot can be achieved through attributes. That also includes error handling; let's see more about that now.

主站蜘蛛池模板: 澄迈县| 南靖县| 枝江市| 常德市| 江川县| 武清区| 兴隆县| 余姚市| 南召县| 江陵县| 新沂市| 乐陵市| 绍兴市| 海兴县| 宽甸| 夏河县| 房产| 温泉县| 德钦县| 上犹县| 大港区| 芦山县| 龙岩市| 江源县| 措美县| 昌宁县| 阿尔山市| 阿勒泰市| 东山县| 清新县| 泰宁县| 佛教| 庆元县| 屯昌县| 晋城| 苍梧县| 陕西省| 丹阳市| 富蕴县| 措勤县| 海晏县|