Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
При обработке запроса система маршрутизации автоматически выдергивает из строки запроса данные для параметров маршрута, не зависимости от их содержимого, основываясь на сегментной структуре адреса 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 нормально был бы обработан.
Подобным образом мы можем задать ограничения и для других параметров. Например, пусть параметр 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" });