Шаблон маршрута, который сопоставляется с конечной точкой, может иметь параметры. Параметры имеют имя и определяются в шаблоне маршрута внутри фигурных скобок: {название_параметра}
Например, определим конечную точку, которая принимает параметр:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map("/users/{id}", (string id) => $"User Id: {id}"); app.Map("/users", () => "Users Page"); app.Map("/", () => "Index Page"); app.Run();
Здесь определено три конечных точки, которые используются шаблоны маршрутов "/users/{id}"
, "/users"
и "/"
. Причем шаблон маршрута
для первой конечной точки принимает параметр с именем id
:
"/users/{id}
Параметр id будет представлять содержимое последнего сегмента. Например, в пути запроса "/users/134" последний сегмент "134" как раз будет представлять параметр id. Если же параметр id не передается, а путь запроса - "/users", то такой запрос обрабатывается второй конечной точкой.
Если маршрут принимает параметр, то в делегате-обработчике маршрута мы можем получить значение этого параметра. Для этого мы можем просто определить действие, которое принимает соответствующий параметр:
(string id) => $"User Id: {id}"
То есть здесь через параметр id
мы получаем одноименный параметр маршрута и далее можем его использовать при обработке запроса.
Стоит отметить, что название параметра маршрута и название параметра лямбда-выражения совпадают.
Также стоит отметить, что здесь для параметра id указан тип - тип string
(то есть здесь мы ожидаем получить через параметр маршрута некоторую строку). Поскольку метод Map может принимать в качестве второго параметра
делегат RequestDelegate, который тоже принимает один параметр - HttpContext, то, если не указать тип, то делегат-обработчик будет рассматриваться именно как RequestDelegate.
Подобным образом можно определять и большее количество параметров маршрута:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map( "/users/{id}/{name}", (string id, string name) => $"User Id: {id} User Name: {name}" ); app.Map("/users", () => "Users Page"); app.Map("/", () => "Index Page"); app.Run();
В данном случае маршрут первой конечной точки принимает два параметра - id и name:
Следует учитывать, что если параметры маршрута определяются подряд, то между ними должен располагаться разделитель. Например, следующий шаблон маршрута работать не будет:
"/users/{id}{name}"
так как между параметрами id
и name
нет разделителя.
Обычно в качестве разделителя выступает слеш, который оформляет отдельный сегмент в пути запроса. Но это необязательно. В качестве разделителя могут применяться и другие символы. Например, установим в качестве разделителя дефис:
app.Map( "/users/{id}-{name}", (string id, string name) => $"User Id: {id} User Name: {name}" );
Более того это может быть набор символов:
app.Map( "/users/{id}and{name}", (string id, string name) => $"User Id: {id} User Name: {name}" );
Если обработчик маршрута выносится в отдельный метод, то он также может определять параметры, который сопоставляются с параметрами маршрута по имени:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map("/users/{id}/{name}", HandleRequest); app.Map("/users", () => "Users Page"); app.Map("/", () => "Index Page"); app.Run(); string HandleRequest(string id, string name) { return $"User Id: {id} User Name: {name}"; }
Параметры маршрута могут быть необязательными. Чтобы определить параметр как необязательный, после его названия указывается знак вопроса. Например, определим следующее приложение:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map("/users/{id?}", (string? id) => $"User Id: {id??"Undefined"}"); app.Map("/", () => "Index Page"); app.Run();
Шаблон маршрута первой конечной точки состоит из двух сегментов, причем второй сегмент представляет параметр id, который помечен как необязательный. А это значит, что мы можем в запросе игнорировать значение для этого сегмента. Например, данный шаблон будет соответствовать двум следующим url:
/users/ /users/23
Необязательные параметры следует помещать в конце шаблона маршрута, как в случае с параметром id в примере выше. То есть, к примеру, шаблон "/users/{id?}/{name}" не будет работать корректно, если мы для параметра id не передадим значение. А вот шаблон "/users/{name}/{id?}" будет работать нормально.
Параметрам маршрута также можно назначить значения по умолчанию на случай, если им не переданы значения:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map( "{controller=Home}/{action=Index}/{id?}", (string controller, string action, string? id) => $"Controller: {controller} \nAction: {action} \nId: {id}" ); app.Run();
Здесь определена одна конечная точка, которая использует следующий шаблон маршрута:
"{controller=Home}/{action=Index}/{id?}"
То есть шаблон состоит из трех параметров. Параметр "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 |
Мы можем обозначить любое количество сегментов в запросе, чтобы не быть жестко привязанным к числу сегментов с помощью параметра со знаком * ("звездочка") или ** (две звездочки) (это так называемый catchall-параметр):
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Map("users/{**info}", (string info) =>$"User Info: {info}"); app.Map("/", () => "Index Page"); app.Run();
Для первой конечной точки определяется шаблон маршрута, в котором параметр info
будет представлять все, что идет после "/users". Это может быть в том числе пустая строка.