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

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

При обработке запроса система маршрутизации на основании шаблон маршрута автоматически извлекает из строки запроса значения для параметров маршрута вне зависимости от содержимого этих значений. Однако это не всегда бывает удобно. Например, мы хотим, чтобы какой-то параметр представлял только числа, а другой параметр начинался строго с определенного символа. И для этого необходимо задать ограничения маршрута (route constraints).

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

Вначале рассмотрим следующую ситуацию. Пусть у нас есть следующее приложение:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Map("/users/{id}", (int id) => $"User Id: {id}");
app.Map("/", () => "Index Page");

app.Run();

Первая конечная точка использует маршрут, который подразумевает наличие параметра id. А в обработчике маршрута мы хотим получить значение этого параметра в виде числа. То есть мы ожидаем, что в пути запроса будет передаваться число, например, "/users/123". Тем не менее мы можем передать вместо числа и строку:

Ограничения маршрутов в ASP.NET Core и C#

На скриншоте выше обращение идет по адресу "/users/hello". И этот путь запроса в принципе соответствует шаблону маршрута "/users/{id}". В этом случае параметр маршрута id получит значение "hello", а для обработки запроса будет запущено действие

(int id) => $"User Id: {id}";

Однако параметр id обработчика представляет тип int, а строка "hello" никак не может быть конвертирована в число. Соответственно мы получим ошибку при преобразовании, о чем собственно и говорит скриншот.

Теперь применим ограничения - укажем, что параметр id в маршруте должен представлять тип int:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Map("/users/{id:int}", (int id) => $"User Id: {id}");
app.Map("/", () => "Index Page");

app.Run();

Для установки ограничения после названия параметра через двоеточие указывается название ограничения. Ограничение int указывает, что параметр должен представлять тип int.

В этом случае нам надо передать этому параметру число:

Установка ограничений для параметров маршрута в ASP.NET Core и C#

Да, мы по-прежнему можем передавать в пути запроса строку вместо числа:

Установка ограничений для параметров маршрута в ASP.NET Core и C#

Но в этом случае инфраструктура ASP.NET Core просто не сможет сопоставить данный путь запроса с шаблоном маршрута. И клиент получит ошибку 404, то есть ресурс не найден.

ASP.NET Core предоставляет следующий ряд ограничений маршрута:

  • int

    Соответствие целому числу. Представляет класс IntRouteConstraint

    {id:int}
  • bool. Представляет класс BoolRouteConstraint

    Соответствие значению true или false

    {active:bool}
  • datetime

    Соответствие дате и времени. Представляет класс DateTimeRouteConstraint

    {date:datetime}
  • decimal

    Соответствие значению decimal. Представляет класс DecimalRouteConstraint

    {price:decimal}
  • double

    Соответствие значению типа double. Представляет класс DoubleRouteConstraint

    {weight:double}
  • float

    Соответствие значению типа float. Представляет класс FloatRouteConstraint

    {height:float}
  • guid

    Соответствие значению типа Guid. Представляет класс GuidRouteConstraint

    {id:guid}
  • long

    Соответствие значению типа long. Представляет класс LongRouteConstraint

    {id:long}
  • minlength(value)

    Строка должна иметь символов не меньше value. Представляет класс MinLengthRouteConstraint

    {name:minlength(3)}
  • maxlength(value)

    Строка должна иметь символов не больше value. Представляет класс MaxLengthRouteConstraint

    {name:maxlength(20)}
  • length(value)

    Строка должна иметь ровно столько символов, сколько определено в параметре value. Представляет класс LengthRouteConstraint

    {name:length(10)}
  • length(min, max)

    Строка должна иметь символов не меньше min и не больше max. Представляет класс LengthRouteConstraint

    {name:length(3, 20)}
  • min(value)

    Число должно быть не меньше value. Представляет класс MinRouteConstraint

    {age:min(3)}
  • max(value)

    Число должно быть не больше value. Представляет класс MaxRouteConstraint

    {age:max(20)}
  • range(min, max)

    Число должно быть не меньше min и не больше max. Представляет класс RangeRouteConstraint

    {age:range(18, 99)}
  • alpha

    Строка должна состоять из одного и более алфавитных символов. Представляет класс AlphaRouteConstraint

    {name:alpha}
  • regex(expression)

    Строка должна соответствовать регулярному выражению expression. Представляет класс RegexRouteConstraint

    {phone:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}
  • required

    Параметр является обязательным, и его значение должно быть определено. Представляет класс RequiredRouteConstraint

    {name:required}

Каждое подобное ограничени представляет определенный класс. Все классы ограничений находятся в пространстве имен Microsoft.AspNetCore.Routing.Constraints

Ограничения можно комбинировать. При применении нескольких ограничений одновременно, они отделяются друг о друга двоеточием Например:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Map(
    "/users/{name:alpha:minlength(2)}/{age:int:range(1, 110)}",
    (string name, int age) => $"User Age: {age} \nUser Name:{name}"
);
app.Map(
    "/phonebook/{phone:regex(^7-\\d{{3}}-\\d{{3}}-\\d{{4}}$)}/",
    (string phone) => $"Phone: {phone}"
);
app.Map("/", () => "Index Page");


app.Run();

Первая конечная точка использует шаблон маршрута

"/users/{name:alpha:minlength(2)}/{age:int:range(1, 110)}"

Здесь предполагается, что параметр name принимает только алфавитные символы, а его минимальная длина должна представлять два символа. Второй же параметр маршрута - age должен представлять целое число и должен находиться в диапазоне между 1 и 110:

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

Вторая конечная точка использует шаблон маршрута

"/phonebook/{phone:regex(^7-\\d{{3}}-\\d{{3}}-\\d{{4}}$)}"

Параметр phone принимает номер телефона в формате 7-ххх-ххх-хххх, любые другие форматы будут некорректными:

Регулярные выражения в ограничениях маршрута в ASP.NET Core и C#
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850