Работа с маршрутами

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

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

Рассмотрим, как происходит работа с маршрутами. При удачном сопоставлении адреса URL определенному маршруту у объекта RouteContext устанавливаются свойства Handler и RouteData. Как мы посмотрели ранее, через свойство Handler устанавливается и потом вызывается делегат, который обрабатывает запрос по маршруту.

А свойство RouteData предназначено для хранения информации о маршруте и его значениях. Оно представляет объект одноименного класса RouteData, который имеет ряд свойств, содержащих информацию об обрабатываемом маршруте:

  • Values представляет словарь значений маршрута. Эти значения получены с помощью сегментирования строки запроса URL. При обработке мы можем использовать эти значения.

  • DataTokens содержит набор дополнительных данных, которые связаны с обрабатываемым маршрутом. Однако если данные в RouteData.Values должны быть легко преобразованы в строки и обратно, то в RouteData.DataTokens могут быть данные любых типов.

  • Routers хранит список маршрутов, которые использовались для успешного сопоставления с запросом. Первый объект в этом списке представляет коллекцию маршрутов, которая применяется для генерации URL. А последний элемент этого списка - собственно тот маршрут, который совпал с запросом.

И все эти данные мы можем получить при обрабтке запроса. Однако делегат RequestDelegate, который обрабатывает запрос в качестве параметра принимает не объект RouteContext, а объект HttpContext. Например:

private async Task Handle(HttpContext context)
{
    await context.Response.WriteAsync("Hello ASP.NET Core");
}

Но у объекта HttpContext есть метод расширения GetRouteData(), который позволяет получить объект RouteData:

RouteData routeData = context.GetRouteData();

Для получения отдельных данных из словаря RouteData.Values также можно использовать еще один метод класса HttpContext - метод context.GetRouteValue()

string controller = context.GetRouteValue("controller").ToString();

Например, получим параметры запроса:

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

namespace RoutingApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRouting();
        }

        public void Configure(IApplicationBuilder app)
        {
            var myRouteHandler = new RouteHandler(Handle);
            var routeBuilder = new RouteBuilder(app, myRouteHandler);
            routeBuilder.MapRoute("default", "{action=Index}/{name}-{year}");
            app.UseRouter(routeBuilder.Build());

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }

        private async Task Handle(HttpContext context)
        {
            var routeValues = context.GetRouteData().Values;
            var action = routeValues["action"].ToString();
            var name = routeValues["name"].ToString();
            var year = routeValues["year"].ToString();
            await context.Response.WriteAsync($"action: {action} | name: {name} | year:{year}");
        }
    }
}
Параметры маршрута в ASP.NET Core

Добавление маршрутов

Чтобы добавить новые маршруты, нам надо последовательно вызвать несколько методов routeBuilder.MapRoute(), передав в них все необходимые параметры. Например:

var myRouteHandler = new RouteHandler(Handle);
var routeBuilder = new RouteBuilder(app, myRouteHandler);
routeBuilder.MapRoute("default", "{action=Index}/{name}-{year}");
routeBuilder.MapRoute("default2", "{controller}/{action}/{id?}");
app.UseRouter(routeBuilder.Build());

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

При определении маршрутов важно их определять так, чтобы у системы маршрутизации не возникало неоднозначности, какой маршрут использовать. Возьмем два маршрута, определенные выше, и запрос http://localhost:5634/index/lumia-2015. На первый взгляд он соответствует первому маршруту. И параметры маршрутизации распределятся следующим образом:

action

index

name

lumia

year

2015

Но этому же запросу также соответствует и второй маршрут, так как этот маршрут соответствует трехсегментному запросу, в котором последний сегмент необязателен:

controller

index

action

lumia-2015

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850