Маршрутизация конечной точки в ASP.NET Core 2.2 не работает - PullRequest
0 голосов
/ 25 апреля 2019

Обновление (2)

@ poke, кажется, понял это, и похоже, что проблема с самой конечной маршрутизацией в пользу {*url}, если есть очевидная неоднозначность с другими более высокимимаршруты.

Обновление (1)

@ poke прокомментировал, что у меня была опечатка на маршруте {*url}, где t в контроллер отсутствует.После исправления, что маршрут {*url} начал работать, а действие DefaultController.Gone работало.

НО! Теперь странное поведение снова начинает возникать.После исправления {*url} переход к /settings, который должен соответствовать маршруту {controller}/{action}, не выполняется и возвращается к маршруту {*url}.

Если я удаляю маршрут {*url} изрегистрация тогда /settings снова работает.Маршрут {action} по-прежнему не работает.

Оригинал

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

Я работаю над приложением для блогов ASP.NET Core 2.2 для себя, и у меня возникают необъяснимые проблемы с получением маршрутизации на работу.Проведя полдня, крича на свои экраны, я решил сделать шаг назад и начать новый проект, который был полностью изолирован.Почему-то проблемы сохранялись в новом проекте.Я разобрал его почти до голодного скелета и до сих пор не могу заставить работать маршруты.Маршруты, которые я пытаюсь настроить:

settings/{controller}/{id:int}/{action} - works
settings/{controller}/{action} - works
blog/{*slug} - works
blog/{skip:int?} - works
{controller}/{action} - works
{action} - doesn't work
{*url} - doesn't work

В частности, у меня проблемы с последними двумя маршрутами.

Маршрут {action} не генерируется для простых действийкак DefaultController.About, даже если он не имеет ограничений, все, что у него есть, это значения по умолчанию для PostsController.List, потому что я хочу, чтобы список сообщений отображался для корневого URL.

{*url} просто не кажетсяработать на всех.Я хочу использовать его как мой последний запасной вариант, и по умолчанию он равен DefaultController.Gone, но если я просто нажму на клавиатуре для какого-то бессмысленного URL, все, что я получу, это ошибка 404.

Я чувствую, что проблема связана сDefaultController, поскольку в нем есть действия About и Gone, и ни один из них, похоже, не работает, но я просто не могу понять, как это сделать.Он буквально ничего не делает, но визуализирует представления, как и другие контроллеры.

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

Program.cs

public sealed class Program {
    public static async Task Main(
        string[] args) => await WebHost.CreateDefaultBuilder(args)
                                       .UseStartup<Startup>()
                                       .Build()
                                       .RunAsync();
}

Startup.cs

public class Startup {
    public void ConfigureServices(
        IServiceCollection services) {
        services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Latest);
    }

    public void Configure(
        IApplicationBuilder app) {
        app.UseMvc(
            r => {
                //  /settings/{controller}/{id}/{action}
                r.MapRoute("600", "settings/{controller}/{id:int}/{action}", null, new {
                    controller = "Categories|Tags"
                });

                //  /settings/{controller}/{action}
                r.MapRoute("500", "settings/{controller}/{action}", null, new {
                    controller = "Categories|Tags"
                });

                //  /blog/*
                r.MapRoute("400", "blog/{*slug}", new {
                    action = "Show",
                    controller = "Posts"
                });

                //  /blog/{skip}
                r.MapRoute("300", "blog/{skip:int?}", new {
                    action = "List",
                    controller = "Posts"
                });

                //  /{controller}/{action}
                r.MapRoute("200", "{controller}/{action=Default}", null, new {
                    controller = "Settings|Tools"
                });

                //  /{action}
                r.MapRoute("100", "{action}", new {
                    action = "List",
                    controller = "Posts"
                });

                //  /*
                r.MapRoute("-1", "{*url}", new {
                    action = "Gone",
                    conroller = "Default"
                });
            });
    }
}

CategoriesController.cs

public sealed class CategoriesController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Category added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Category {id} removed");
}

DefaultController.cs

public sealed class DefaultController :
    Controller {
    [HttpGet]
    public IActionResult About() => View();

    [HttpGet]
    public IActionResult Gone() => View();
}

About.cshtml (по умолчанию)

<h1>DEFAULT.ABOUT</h1>

Gone.cshtml (по умолчанию)

<h1>DEFAULT.GONE</h1>

PostsController.cs

public sealed class PostsController :
    Controller {
    [HttpGet]
    public IActionResult List(
        int? skip) => View();

    [HttpGet]
    public IActionResult Show(
        string slug) => View();
}

List.cshtml (сообщения)

<h1>POSTS.LIST</h1>
<a asp-action="Show" asp-controller="Posts" asp-route-slug="test-test-test">Show a Post</a>

Show.cshtml (сообщения)

<h1>POSTS.SHOW</h1>

SettingsController.cs

public sealed class SettingsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}

Default.cshtml (Настройки)

<h1>SETTINGS.DEFAULT</h1>
<a asp-action="Add" asp-controller="Categories">Add a Category</a>
<br />
<a asp-action="Remove" asp-controller="Categories" asp-route-id="1">Remove a Category</a>
<hr />
<a asp-action="Add" asp-controller="Tags">Add a Tag</a>
<br />
<a asp-action="Remove" asp-controller="Tags" asp-route-id="1">Remove a Tag</a>

TagsController.cs

public sealed class TagsController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Tag added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Tag {id} removed");
}

ToolsController.cs

public sealed class ToolsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}

Default.cshtml

<h1>TOOLS.DEFAULT</h1>

_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <a asp-action="List" asp-controller="Posts">Blog</a>
    <br />
    <a asp-action="Default" asp-controller="Tools">Tools</a>
    <br />
    <a asp-action="About" asp-controller="Default">About</a>
    <br />
    <a asp-action="Default" asp-controller="Settings">Settings</a>
    <br />
    @RenderBody()
</body>
</html>

1 Ответ

1 голос
/ 25 апреля 2019

{action} - не работает

Это не работает, потому что оно должно соответствовать действующему действию.Так что это работает для /Show или /List, так как вы работаете на PostsController.Это также работает для /, поскольку action по умолчанию List.

{*url} - не работает

Этот будет работает, если вы установите значение по умолчанию controller вместо conroller:

r.MapRoute("-1", "{*url}", new
{
    action = "Gone",
    controller = "Default"
});

<a asp-action="About" asp-controller="Default">About</a>

Обратите внимание, что этот маршрут также будетне соответствует, потому что нет никакого маршрута к этому действию.Маршруты {controller}/{action} ограничены SettingsController и ToolsController, поэтому маршрут не будет совпадать.Вам нужно будет настроить ограничение или добавить другой маршрут, чтобы это работало.

Кстати.в качестве общего предложения: Как вы, вероятно, заметили, управление таким множеством маршрутов довольно сложно.Часто проще просто использовать атрибутную маршрутизацию с явными маршрутами.Вы также можете смешать их с маршрутизацией на основе шаблонов, чтобы получить лучшее из обоих миров.


Странно /settings, который должен соответствовать маршруту {controller}/{action}, теперь терпит неудачу и возвращается к{*url} маршрут.Если я удаляю маршрут {*url} из регистраций, то /settings снова работает.

Это побочный эффект от объединения маршрутов settings/{controller}/{action} и {controller}/{action=Default}.

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

К сожалению, маршрутизация к конечной точке вИзвестно, что ASP.NET Core 2.2 разбит на несколько особых случаев, поэтому он обновляется до версии 3.0, которая, будем надеяться, решит все проблемы.При этом я открыл вопрос об этой конкретной проблеме и сообщил о своих выводах.Возможно, для этого есть простое решение.

Одним из простых обходных путей может быть изменение шаблона маршрута settings/{controller}/{action} на использование префикса, отличного от settings, чтобы не было двусмысленности.Это, кажется, чтобы решить проблемы.

...