ASP .Net Core меняет маршрут во время выполнения - PullRequest
0 голосов
/ 18 октября 2018

Моя проблема: у меня есть несколько классов контроллеров, и я хочу, чтобы их маршрут менялся в зависимости от некоторого значения (назовем его ID), которое находится во внешнем конфигурационном файле (может измениться).Этот идентификатор не является постоянным, он генерируется при запуске приложения.

[Route("api/projects/" + idForTest1FromConfigFile]
public class Test1Controller : Controller 
{
    public IActionResult Index()
    {
        return View();
    }
}

ОБНОВЛЕНИЕ Тогда у меня есть Test2Controller, который в основном совпадает с Test1Controller, но возвращает различные представления

[Route("api/projects/" + idForTest2FromConfigFile]
public class Test2Controller : Controller 
{
    public IActionResult Index()
    {
        return View();
    }
}

Так скажем, в моем конфигурационном файле у меня есть:

Test1 : 123
Test2 : 456

Поэтому, когда я звоню https://localhost:44391/api/projects/123/Index, я хочу получить страницу индекса из Test1Controller, а когда я звоню https://localhost:44391/api/projects/456/IndexЯ хочу получить страницу индекса от Test2Controller

Есть ли способ, которым это может быть сделано?Спасибо

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Если вы хотите использовать более гибкий подход, вы можете рассмотреть возможность использования пользовательского соглашения о контроллере, которое может быть реализовано с использованием интерфейса IControllerModelConvention .Используя это, вы можете передать объект конфигурации в пользовательское соглашение и применить маршруты, используя это.Есть несколько способов решения этой проблемы, но вот пример реализации:

public class RoutingControllerModelConvention : IControllerModelConvention
{
    private readonly IConfiguration _configuration;

    public RoutingControllerModelConvention(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void Apply(ControllerModel controllerModel)
    {
        const string RouteTemplate = "/api/projects/<id>/[action]";

        var routeId = _configuration["RouteIds:" + controllerModel.ControllerName];
        var firstSelector = controllerModel.Selectors[0];

        if (firstSelector.AttributeRouteModel == null)
            firstSelector.AttributeRouteModel = new AttributeRouteModel();

        firstSelector.AttributeRouteModel.Template = RouteTemplate.Replace("<id>", routeId);
    }
}

В этом примере я беру экземпляр IConfiguration в конструктор, который заполняется из следующего appsettings.json:

{
    "RouteIDs": {
        "Test1": 123,
        "Test2": 234
    }
}

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

В методе RoutingControllerModelConvention.Apply, который вызывается для каждого контроллера в вашем проекте, мы ищем соответствующее значение из нашего экземпляра IConfiguration, где мы используем controllerModel.ControllerName, чтобы получить, например, Test1.В этом примере это дает нам значение 123.Затем мы берем первый селектор (всегда есть хотя бы один) и, в конечном счете, устанавливаем шаблон его маршрута равным /api/projects/123/[action].

. При таком подходе вам не нужно применять атрибут [Route]к самому контроллеру, и вам не нужно использовать MapRoute в Startup.Все, что вам нужно сделать при добавлении новых контроллеров, это создать контроллер и добавить запись (в этом примере) appsettings.json, соответственно.

Чтобы использовать это пользовательское соглашение, вам необходимонастройте его в Startup.ConfigureServices:

services.AddMvc(options =>
{
    options.Conventions.Add(new RoutingControllerModelConvention(Configuration));
});

Для получения дополнительной информации модель приложения и соглашения задокументированы здесь: Работа с моделью приложения в ASP.NET Core .


Я ценю, что приведенная выше реализация не идеальна: вам нужно проверить null s и имена контроллеров, которые не найдены в конфигурации, и т. Д. Это должно как минимум послужитьначать с подхода, который достаточно гибок.

0 голосов
/ 18 октября 2018

Если этот идентификатор генерируется при запуске, но , тогда это константа, вы можете просто сгенерировать динамическое отображение маршрута при вызове UseMvc() внутри метода Configure:

var id1 = GetIdFromSomewhere();
var id2 = GetIdFromSomewhere();
app.UseMvc(routes =>
{
    // Test1Controller
    routes.MapRoute("test-route-1",
        "/api/projects/" + id1 + "/{action}",
        new { controller = "Test1", action = "Index" });

    // Test2Controller
    routes.MapRoute("test-route-2",
        "/api/projects/" + id2 + "/{action}",
        new { controller = "Test2", action = "Index" });

    // …
});
...