Атрибуты маршрутизации

Последнее обновление: 25.03.2022

Кроме маршрутизации на основе условностей или Convention-Based Routing, которая рассматривалась в прошлых темах, фреймворк MVC позволяет использовать в приложении маршрутизацию на основе атрибутов. Такой тип маршрутизации еще называется Attribute-Based Routing. Атрибуты предоставляют более гибкий способ определения маршрутов.

Для определения маршрута непосредственно в контроллере, необходимо использовать атрибут [Route]:

public class HomeController : Controller
{
	[Route("Home/Index")]
	public IActionResult Index()
	{
		return Content("ASP.NET Core на metanit.com");
	}
	[Route("About")]
	public IActionResult About()
	{
		return Content("About site");
	}
}

В данном случае метод Index будет обрабатывать запросы по адресу "Home/Index", а метод About по адресу "About".

Если в проекте планируется использовать только маршрутизацию на основе атрибутов, то в файле Program.cs мы можем не определять никаких маршрутов. В этом случае для подключения в приложении возможностей маршрутизации достаточно применить метод MapControllers без определения конкретных маршрутов:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

var app = builder.Build();

app.MapControllers(); 

app.Run();
Attribute-Based Routing in ASP.NET Core MVC и C#

Но также мы можем комбинировать способы маршрутизации. При чем здесь надо учитывать, что маршрутизация на основе атрибутов имеет больший приоритет. Например, определим следующее действие контроллера:

public class HomeController : Controller
{
    [Route("homepage")]
    public string Index() => "ASP.NET Core MVC on METANIT.COM";
}

В качестве параметра атрибут Route принимает шаблон URL, с которым будет сопоставляться запрошенный адрес. И даже если у нас определен стандартный маршрут в файле Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

var app = builder.Build();

app.MapControllerRoute(
	name: "default",
	pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Запрос типа http://localhost:xxxx/home/index работать не будет, так как мы явно указали с помощью атрибута, что метод Index контроллера Home будет обрабатывать только запросы http://localhost:xxxx/homepage

Атрибуты маршрутизации в контроллерах ASP.NET Core MVC и C#

Определение маршрутов с помощью атрибутов подчиняется тем же правилам, что определение маршрутов с помощью методе MapControllerRoute(). Например, используем параметры и ограничения:

public class HomeController : Controller
{
    [Route("{name:minlength(3)}/{age:int}")]
    public string Person(string name, int age)
    {
        return $"name={name} | age={age}";
    }
}

И к такому методу мы сможем обратиться с запросом типа http://localhost:xxxx/tom/37.

Атрибуты контроллеров и маршрутизация в ASP.NET Core MVC и C#

Или другой пример - применение необязательного параметра:

public class HomeController : Controller
{
    [Route("Home/Index/{id?}")]
	public string Test(int? id)
	{
		if(id is not null)
			return $"Параметр id={id}";
		else
			return $"Параметр id неопределен";
	}
}

И к такому методу мы сможем обратиться с запросом типа http://localhost:xxxx/home/index или добавить параметр http://localhost:xxxx/home/index/5.

Использование префиксов

Допустим, у нас есть несколько методов, для которых определен свой маршрут, и мы хотим, чтобы эти маршруты начинались с одного определенного префикса. Например:

public class HomeController : Controller
{
    [Route("main/index/{name}")]
    public string Index(string name) => name;

    [Route("main/{id:int}/{name:maxlength(10)}")]
    public string Test(int id, string name) => $" id={id} | name={name}";
}

Вместо того, чтобы добавлять префикс "main" к каждому маршруту, мы могли бы определить его глобально для всего контроллера:

[Route("main")]
public class HomeController : Controller
{
    [Route("index/{name}")]
    public string Index(string name) => name;

    [Route("{id:int}/{name:maxlength(10)}")]
    public string Test(int id, string name) => $" id={id} | name={name}";
}

Параметры controller и action

От всех параметров шаблона маршрутов в атрибутах отличаются два параметра controller и action, которые ссылаются соответственно на контроллер и его действие и которые также можно получить в методе контроллера:

public class HomeController : Controller
{
    [Route("{controller}/{action}")]
    public string Index()
    {
        var controller = RouteData.Values["controller"];
        var action = RouteData.Values["action"];
        return $"controller: {controller} | action: {action}";
    }
}

public class HomeController : Controller
{
    [Route("{controller}/{action}")]
    public string Index(string controller, string action)
    {
        return $"controller: {controller} | action: {action}";
    }
}

Множественные маршруты

С помощью атрибутов можно задать несколько маршрутов для одного метода. Например:

[Route("{controller}")]
public class HomeController : Controller
{
   [Route("")]     // сопоставляется с Home
   [Route("Index")] // сопоставляется с Home/Index
    public string Index() => "Index Page";
}

Также для контроллера можно задать сразу несколько маршрутов:

[Route("Store")]
[Route("{controller}")]
public class HomeController : Controller
{
   [Route("Main")]     // сопоставляется с Home/Main, либо с Store/Main
   [Route("Index")] // сопоставляется с Home/Index, либо с Store/Index
   public string Index() => "Index Page";
}

Значения параметров по умолчанию

Также параметры в атрибутах могут иметь значения по умолчанию:

public class HomeController : Controller
{
    [Route("{controller=Home}/{action=Index}")]
    public string Index(string controller, string action)
    {
        return $"controller: {controller} | action: {action}";
    }
}

В данном случае методом Index будут сопоставляться такие запросы как http://localhost:xxxx/home/index, http://localhost:xxxx/home/ и http://localhost:xxxx/

Подобным образом можно задавать значения по умолчанию для других параметров, например:

public class HomeController : Controller
{
    [Route("{name=Tom}")]
    public string Index(string name) => $"Name: {name}";
}

В данном случае если параметру name не передано значение, то он по умолчанию принимает в качестве значения строку "Tom"

Параметры в атрибутах маршрутизация в ASP.NET Core MVC и C#
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850