Определение маршрутов

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

Основой для определения маршрута служит его шаблон. На основе шаблона маршрута система маршрутизации определяет, будет ли обрабатываться запрос, а если и будет, то каким контроллером и каким методом контроллера.

Например, возьмем простейший проект ASP.NET Core и в файле Program.cs один маршрут:

var builder = WebApplication.CreateBuilder(args);

// добавляем поддержку контроллеров с представлениями
builder.Services.AddControllersWithViews();

var app = builder.Build();

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action}");

app.Run();

Здесь шаблон маршрута выглядит следующим образом:

"{controller}/{action}"

Шаблон маршрута может иметь параметры. Параметры имеют имя и определяются в шаблоне маршрута внутри фигурных скобок: {название_параметра}. Например, в шаблоне маршрута выше определено два параметра: controller и action.

И когда приходит запрос к приложению, система маршрутизации сопоставляет запрошенный путь, если сопоставление прошло успешно, то система маршрутизации использует параметр "controller" для получении имени контроллера, а параметр "action" - для определения действия этого контроллера, который будет обрабатывать запрос.

Если в шаблоне маршрута идут подряд несколько параметров, то между ними должен располагаться разделитель. Обычно в качестве разделителя выступает слеш (как в данном случае), который оформляет отдельный сегмент в пути запроса. То есть в случае выше каждый отдельный параметр маршрута отделен от другого слешем, поэтому будет представлять отдельный сегмент пути запроса. Например, если пришел запрос по пути "/home/index/", то первый сегмент "/home/" будет проецироваться на параметр "controller", поэтому будет выбран контроллер Home. Второй сегмент - "/index/" будет проецироваться на параметр "action", соответственно для обработки этого запроса будет выбран метод Index контроллера Home.

Пусть в проекте определен контроллер HomeController со следующим кодом:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public string Index() => "Index Page";
        public string About() => "About Page";
    }
}

Таким образом, при запросе Home/Index, запрос будет обрабатываться методом Index контроллера Home, а запрос Home/About - методом About того же контроллера.

Система маршрутизации в ASP.NET Core MVC и C#

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

var builder = WebApplication.CreateBuilder(args);

// добавляем поддержку контроллеров с представлениями
builder.Services.AddControllersWithViews();

var app = builder.Build();

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(name: "default", pattern: "{controller}/{action}/{id}");
app.MapControllerRoute(name: "name_age", pattern: "{controller}/{action}/{name}/{age}");

app.Run();

Здесь первый маршрут - "default" принимает третий параметр - id, который располагается в третьем сегменте строки запроса.

Второй маршрут - "name_age" принимает дополнительно два параметра - name и age, который располагаются соответственно в третьем сегменте и четвертом сегментах строки запроса.

Для тестирования маршрутов определим следующий контроллер:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public string Index(int id) => $"Index Page. Id: {id}";
        public string About(string name, int age) => $"About Page. Name: {name}  Age: {age}";
    }
}

И в данном случае, если к приложению придет запрос типа "Home/Index/6", система маршрутизации сможет сопоставить этот запрос с первым маршрутом - маршрутом "default", который также содержит из трех сегментов, и значение последнего сегмента - число 6 будет передано в метод Index через параметр id:

передача параметров через маршруты в ASP.NET Core MVC и C#

Если же к приложению придет запрос из четырех сегментов типа "Home/About/Tom/37", то система маршрутизации сможет сопоставить этот запрос со вторым маршрутом - маршрутом "name_age". Тогда значение третьего сегмента будет передано в метод через параметр name, а значение четвертого сегмента - через параметр age:

получение параметров маршрутов в контроллерах ASP.NET Core MVC и C#

Статические сегменты

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

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(
    name: "default", 
    pattern: "api/{controller}/{action}/{id}");

В данном случае шаблон маршрута начинается со статического сегмента api/. Таким образом, этому маршруту будут соответствовать все маршруты, которые состоят из четырех сегментов, где первый сегмент равен "/api", например, запрос https://localhost:7288/api/Home/Index/6

Необязательные параметры маршрутов

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

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

В этом шаблоне маршрута третий сегмент представляет параметр id, который помечен как необязательный. А это значит, что мы можем в запросе игнорировать значение для этого сегмента. Например, данный шаблон будет соответствовать двух- и трехсегментным запросам, например, двум следующим url:

/home/index
/home/index/23

Для тестирования определим следующий контроллер:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public string Index(int? id)
        {
            if(id is not null) return $"Product Id: {id}";
            
            return "Product List";
        }
    }
}

Здесь, если параметр id определен, то метод Index возвращает одну строку, если неопределен - то другую:

Необязательные параметры маршрута в ASP.NET Core MVC и C#

Необязательные параметры следует помещать в конце шаблона маршрута, как в случае с параметром id в примере выше. То есть, к примеру, шаблон "{controller}/{action}/{id?}/{name}" не будет работать корректно, если мы для параметра id не передадим значение. А вот шаблон "{controller}/{action}/{name}/{id?}" будет работать нормально.

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

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

var builder = WebApplication.CreateBuilder(args);

// добавляем поддержку контроллеров с представлениями
builder.Services.AddControllersWithViews();

var app = builder.Build();

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(
    name: "default", 
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Здесь определен шаблон маршрута, который состоит из трех параметров. Параметр "controller" имеет значение по умолчанию "Home". Параметр "action" имеет значение по умолчанию "Index". Параметр "id" определен как необязательный. В итоге при различных запросах у нас получатся следующие значения:

Запрос

Параметры запроса

https://localhost:7256/

controller=Home

action=Index

https://localhost:7256/Book

controller=Book

action=Index

https://localhost:7256/Book/Show

controller=Book

action=Show

https://localhost:7256/Book/Show/2

controller=Book

action=Show

id=2

Для установки значений по умолчанию также можно применять параметр defaults метода MapControllerRoute(). Этот параметр представляет объект, свойства которого соответствуют параметрам маршрута. Например, определим следующий маршрут:

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

var app = builder.Build();

app.MapControllerRoute(
    name: "default", 
    pattern: "{action}",
    defaults: new { controller = "Home", action = "Index"});

app.Run();

Здесь шаблон маршрута состоит из одного сегмента, который соответствует параметру "action", то есть представляет действие контроллера. А параметр defaults:

 defaults: new { controller = "Home", action = "Index"}

Устанавливает, что в качестве контроллера по умолчанию будет использоваться контроллер Home, а в качестве действия - метод Index.

Например, пусть у нас будет следующий HomeController:

public class HomeController : Controller
{
    public string Index() => "Index Page";
    public string About() => "About Page";
}

В этом случае запрос типа https://localhost:7288/ будет обрабатываться методом Index контроллера Home, а запрос https://localhost:7288/About - методом About.

Значение по умолчанию в параметрах маршрута в ASP.NET Core MVC и C#

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

app.MapControllerRoute(
    name: "info", 
    pattern: "contact/info",
    defaults: new { controller = "Home", action = "About"});

В данном случае запрос https://localhost:7288/contact/info будет обрабатываться методом About контроллера Home.

Ограничения маршрутов

Для параметров маршрута в MVC, также как и в общем в ASP.NET Core, можно устанавливать ограничения. Подробно ограничения были расписаны в статье Ограничения маршрутов в ASP.NET. В MVC применяется те же ограничения, что и в общем в ASP.NET Core, поэтому в данной статье я не буду их подробно описывать.

Ограничения можно установить непосредственно в шаблоне маршрута:

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

В данном случае указывается, что параметр id может иметь либо значение типа int, либо значение null

Второй способ установки ограничений представляет параметр constraints метода MapControllerRoute:

using Microsoft.AspNetCore.Routing.Constraints; // для типа IntRouteConstraint

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

var app = builder.Build();

app.MapControllerRoute(
    name: "default", 
    pattern: "{controller=Home}/{action=Index}/{id?}",
    constraints: new {id= new IntRouteConstraint()});  // ограничения маршрутов

app.Run();

Параметр constraints принимает объект, в котором свойства соответствуют по названиям параметрам маршрутов, а значения свойств - ограничения, применяемые к одноименным параметрам маршрутов. Так, в данном случае к параметру id применяется ограничение IntRouteConstraint, которое указывает, что id должно представлять значение типа int.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850