Переопределение RouteValueDictionary в ограничении в ASP.NET Core - PullRequest
0 голосов
/ 26 мая 2019

Я только начал использовать ASP.NET Core MVC и хочу, чтобы один маршрут (глобальный слаг) проходил к нескольким контроллерам и действиям в зависимости от того, какой тип страницы я обслуживаю пользователю. Например, я хочу использовать {* slug} для страниц категорий и продуктов.

Я пытаюсь переопределить контроллер по умолчанию и действие в ограничении.

В прошлых версиях MVC вы могли изменить либо значения ["controller"], либо значения ["action"] в ограничении, и он перенаправил бы на соответствующий контроллер и действие.

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        app.UseMvc(routes =>
                    {
                        routes.MapRoute(
                            name: "Category",
                            template: "{*slug}",
                            defaults: new { controller = "Page", action = "Home" },
                            constraints: new { slug = new PageConstraint() }
                            );
                    });

    }

}


public partial class PageConstraint : IRouteConstraint
{
    public virtual bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.UrlGeneration)
        {
            return true;
        }

        var slug = values["slug"] != null ? values["slug"].ToString() : null;

        if (string.IsNullOrWhiteSpace(slug))
        {
            // Homepage
            return true;
        }

        // Get category service
        var categoryService = httpContext.RequestServices.GetRequiredService<ICategoryService>();

        var category = categoryService.GetBySlug(slug);

        if (category == null)
        {
            return false;
        }

        values["controller"] = "Category";
        values["action"] = "Listing";
        values["category"] = category;

        return true;
    }
}

В PageConstraint я проверяю, существует ли Категория, и если она существует, она изменяет Контроллер на Категория и Действие на Перечисление в RouteValueDictionary. Однако когда я отлаживаю код до конца, он все равно переходит на страницу контроллера и домашнюю страницу действия.

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

1 Ответ

0 голосов
/ 28 мая 2019

По вашему требованию вы можете попробовать реализовать пользовательские IRouter

public class RouterFromAppSettings : IRouter
{
    private readonly IRouter _defaulRouter;
    private readonly IConfiguration _config;
    public RouterFromAppSettings(IRouter defaulRouter
        , IConfiguration config)
    {
        _defaulRouter = defaulRouter;
        _config = config;
    }
    public async Task RouteAsync(RouteContext context)
    {
        var controller = _config.GetSection("Router").GetValue<string>("Controller");
        var action = _config.GetSection("Router").GetValue<string>("Action");
        context.RouteData.Values["controller"] = controller;
        context.RouteData.Values["action"] = action;
        await _defaulRouter.RouteAsync(context);
    }
    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        return _defaulRouter.GetVirtualPath(context);
    }
}

, а затем зарегистрировать его в Startup.cs как

app.UseMvc(routes =>
{
    routes.Routes.Insert(0, new RouterFromAppSettings(routes.DefaultHandler,Configuration));

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...