Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
По умолчанию каждому маршруту сопоставляется некоторый шаблон, которому должна соответствовать строка запроса. Однако мы можем уйти от определения шаблонов и построить собственную логику применения маршрута к запросу через реализацию интерфейса Microsoft.AspNetCore.Routing.IRouter.
Этот интерфейс определяет два метода:
public interface IRouter { Task RouteAsync(RouteContext context); VirtualPathData GetVirtualPath(VirtualPathContext context); }
Метод RouteAsync()
предназначен для обработки входящих запросов. А метод GetVirtualPath()
применяется для генерации ссылок в соответствии
с данным маршрутом.
К примеру, добавим в проект класс AdminRoute:
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using System; using System.Threading.Tasks; namespace RoutingApp { public class AdminRoute : IRouter { public VirtualPathData GetVirtualPath(VirtualPathContext context) { throw new NotImplementedException(); } public async Task RouteAsync(RouteContext context) { string url = context.HttpContext.Request.Path.Value.TrimEnd('/'); if (url.StartsWith("/Admin", StringComparison.OrdinalIgnoreCase)) { context.Handler = async ctx => { ctx.Response.ContentType = "text/html;charset=utf-8"; await ctx.Response.WriteAsync("Привет admin!"); }; } await Task.CompletedTask; } } }
Данный класс реализует метод RouteAsync()
, который обрабатывает входящий запрос. В качестве параметра в RouteAsync передается объект
RouteContext, через который мы можем получить доступ к данным запроса. В частности, здесь мы смотрим на первый сегмент строки запроса -
если он начинается со строки "/Admin", то устанавливается обработчик маршрута, который отправляет в качестве ответа сообщение "Привет admin!".
Обработчик маршрута здесь также представляет делегат RequestDelegate, которому в качестве параметра из вызывающей среды передается объект RequestContext.
Метод GetVirtualPath()
в данном случае нам не понабодится, поэтому он остается нереализованным.
Также стоит отметить, что обработка запроса в выше определенном методе RouteAsync существенно отличается от, скажем, следующей реализации метода, которая вроде бы делает то же самое:
public async Task RouteAsync(RouteContext context) { string url = context.HttpContext.Request.Path.Value.TrimEnd('/'); if (url.StartsWith("/Admin", StringComparison.OrdinalIgnoreCase)) { await context.HttpContext.Response.WriteAsync("Привет admin!"); } }
Во втором случае запрос после обработки будет передаваться дальше по списку маршрутов и компонентов middleware, которые имеются в конвейере. А в первом случае запрос будет
обрабатываться только тем делегатом, который установлен для свойства context.Handler
.
Теперь применим этот маршрут в классе Startup:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Routing; namespace RoutingApp { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddRouting(); } public void Configure(IApplicationBuilder app) { var routeBuilder = new RouteBuilder(app); routeBuilder.Routes.Add(new AdminRoute()); routeBuilder.MapRoute("{controller}/{action}", async context => { context.Response.ContentType = "text/html;charset=utf-8"; await context.Response.WriteAsync("двухсегментный запрос"); }); app.UseRouter(routeBuilder.Build()); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
С помощью вызова routeBuilder.Routes.Add(new AdminRoute())
маршрут добавляется на первое место в списке маршрутов. И в случае, если в запросе
первый сегмент будет начинаться с "Admin", то он и будет соответствовать этому маршруту.