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

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

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

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

Для задания ограничений маршрутов применяется одна из перегруженных версий метода MapRoute() класса RouteBuilder. Например, нам надо задать, чтобы имя какого-либо сегмента обязательно начиналось с буквы "H". Тогда мы можем определить соответствующее ограничение для имени с помощью регулярных выражений:

routeBuilder.MapRoute("default", 
        "{controller}/{action}/{id?}", 
        new { action = "Index" },  // параметры по умолчанию
        new { controller = "^H.*" } // ограничения
);

В рамках общей картины:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;

namespace RoutingApp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            var myRouteHandler = new RouteHandler(async context=>
            {
                await context.Response.WriteAsync("Routing content");
            });

            var routeBuilder = new RouteBuilder(app, myRouteHandler);
            routeBuilder.MapRoute("default",
                "{controller}/{action}/{id?}",
                new { action = "Index" } , // параметры по умолчанию
                new { controller = "^H.*" } // ограничения
        );
            app.UseRouter(routeBuilder.Build());

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Standard content");
            });
        }
    }
}

С помощью последнего параметра устанавливаются ограничения маршрута. И если мы направим приложению запрос Book/Index, то маршрут не будет обрабатываться связанным с ним обработчиком, так как имя первого параметра "controller" попадает под ограничение. А запрос Home/Index нормально был бы обработан.

Route Constraints in ASP.NET Core

Подобным образом мы можем задать ограничения и для других параметров. Например, пусть параметр id состоит из двух цифр:

routeBuilder.MapRoute("default", 
        "{controller}/{action}/{id?}", 
        new { action = "Index" },
        new { controller = "^H.*", id = @"\d{2}" }
);

Теперь даже запрос Home/Index/1 не будет сопоставляться с маршрутом, так как параметр id должен состоять из двух цифр.

Фактически в обоих случаях применяется класс RegexRouteConstraint из пространства Microsoft.AspNetCore.Routing.Constraints, который устанавливает ограничение в виде регулярного выражения:

routeBuilder.MapRoute("default", 
        "{controller}/{action}/{id?}", 
        null,
        new { controller = new RegexRouteConstraint("^H.*"), id = new RegexRouteConstraint(@"\d{2}") }
);

Кроме этого класса ASP.NET Core предоставляет еще ряд классов ограничений, которые находятся в пространстве имен Microsoft.AspNet.Routing.Constraints

  • AlphaRouteConstraint: параметр должен состоять только из алфавитных символов английского алфавита

    new {controller=new AlphaRouteConstraint()}
  • BoolRouteConstraint: параметр должен иметь значение true или false

    new {id=new BoolRouteConstraint()}
  • DateTimeRouteConstraint: параметр должен предоставлять объект DateTime

    new {id=new DateTimeRouteConstraint()}
  • DecimalRouteConstraint: параметр должен предоставлять объект decimal

    new {id=new DecimalRouteConstraint()}
  • DoubleRouteConstraint: параметр должен предоставлять объект double

    new {id=new DoubleRouteConstraint()}
  • FloatRouteConstraint: параметр должен предоставлять объект float

    new {id=new FloatRouteConstraint()}
  • GuidRouteConstraint: параметр должен предоставлять объект Guid

    new {id=new GuidRouteConstraint()}
  • HttpMethodRouteConstraint: запрос должен представлять определенный тип - Get, Post и т.д.

    routeBuilder.MapRoute("default",
         "{controller}/{action}/{id?}",
         null,
         new { httpMethod = new HttpMethodRouteConstraint("POST") }
    );
    

    В конструктор HttpMethodRouteConstraint передаются названия допустимых типов запросв. В данном случае маршрут будет обрабатываться только для POST-запросов.

  • IntRouteConstraint: параметр должен предоставлять объект int

    new {id=new IntRouteConstraint()}
  • LengthRouteConstraint: строка, представляющая параметр, должна иметь определенную длину

    new 
    {
        controller = new LengthRouteConstraint(4), // точная длина
        action = new LengthRouteConstraint(3,10) // минимальная и максимальная длина
    }
    
  • LongRouteConstraint: параметр должен предоставлять объект long

    new {id=new LongRouteConstraint()}
  • MaxLengthRouteConstraint / MinLengthRouteConstraint: определяют максимальную и минимальную длину параметра в символах

    new 
    {
        controller = new MaxLengthRouteConstraint(5),
        action = new MinLengthRouteConstraint(3)
    }
    
  • MaxRouteConstraint / MinRouteConstraint: определяют максимальное и минимальное числовое значение для параметра

    new {id=new MinRouteConstraint(4)} // минимальное значение - 4
  • RangeRouteConstraint: параметр должен предоставлять числовое значение int в определенном диапазоне

    new {id=new RangeRouteConstraint(3, 100)} // диапазон от 3 до 100
  • RegexRouteConstraint: задает регулярное значение, которому должен соответствовать параметр

  • OptionalRouteConstraint: определяет ограничение для необязательного параметра. И если параметр имется в запросе, то вступает в силу внутреннее ограничение, задаваемое через свойство InnerConstraint класса OptionalRouteConstraint

  • RequiredRouteConstraint: указывает, что параметр должен обязательно иметь какое-нибудь значение

  • StringRouteConstraint: указывает, что параметр должен обязательно соответствовать определенной строке

    new { controller = new StringRouteConstraint("Store") } // controller должен быть равен "Store"

Составные ограничения

С помощью специального класса CompositeRouteConstraint можно установить сложное ограничение, которое будет включать несколько простых:

routeBuilder.MapRoute(
    name: "default",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller="Home", action = "Index" },
    constraints: new
    {
        action =  new CompositeRouteConstraint(new IRouteConstraint[] 
        {
            new AlphaRouteConstraint(),
            new MinLengthRouteConstraint(5)
        })
});

В данном случае устанавливается, что параметр action должен одновременно состоять только из алфавитных символов и также должен иметь длину не менее 5 символов.

Строчный синтаксис ограничений

ASP.NET Core позволяет также указывать ограничения прямо при определении параметров поле двоеточия в виде сокращений, это так называемые строчные ограничения (inline constraints):

routeBuilder.MapRoute("default", "{controller:regex(^H.*)}/{action}/{id?}");

Ограничение regex фактически применяет класс RegexRouteConstraint. Все подобные встраиваемые ограничения называются по имени классов без суффикса RouteConstraint.

Все строчные ограничения:

  • int

    Соответствие числу

    {id:int}
  • bool

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

    {active:bool}
  • datetime

    Соответствие дате и времени

    {date:datetime}
  • decimal

    Соответствие значению decimal

    {price:decimal}
  • double

    Соответствие значению типа double

    {weight:double}
  • float

    Соответствие значению типа float

    {height:float}
  • guid

    Соответствие значению типа Guid

    {id:guid}
  • long

    Соответствие значению типа long

    {id:long}
  • minlength(value)

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

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

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

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

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

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

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

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

    Число должно быть не меньше value

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

    Число должно быть не больше value

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

    Число должно быть не меньше min и не больше max

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

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

    {name:alpha}
  • regex(expression)

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

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

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

    {name:required}

Например, установим ряд ограничений:

routeBuilder.MapRoute("default", "{controller:length(4)}/{action:alpha}/{id:range(4,100)}");

Если нам надо установить составное ограничение, то все ограничения перечисляются через двоеточие:

routeBuilder.MapRoute(
    name: "default",
    template: "{controller}/{action:alpha:minlength(5)}/{id?}",
    defaults: new { controller="Home", action = "Index" });
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850