ASP.NET Core 2.2中的端点路由不起作用

问题描述 投票:0回答:1

更新(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,但是如果我只是在键盘上猛击一些废话网址,我得到的是404错误。

我觉得这个问题与DefaultController有关,因为AboutGone的行动都在其中,似乎没有人工作,但我似乎无法弄清楚如何。除了渲染视图之外,它实际上什么都不做,就像其他控制器一样。

以下是精简项目的代码。我真的很感激,如果有人可以把它旋转并告诉我我失败的地方,因为我当然无法想象它。

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>
c# asp.net-core routing asp.net-core-2.2
1个回答
1
投票

{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}路线受限于SettingsControllerToolsController,因此路线将不匹配。您需要调整约束或添加其他路由才能使用。

顺便说一句。作为一般建议:正如您可能已经注意到的那样,管理这么多路由映射变得非常复杂。使用显式路由的属性路由通常更容易。您还可以将这些与基于模板的路由混合,以获得两全其美。


奇怪的/settings应该与{controller}/{action}路线匹配现在失败并且回落到{*url}路线。如果我从注册中删除{*url}路线,那么/settings再次工作。

这似乎是来自settings/{controller}/{action}{controller}/{action=Default}路线的副作用。

我现在已经调试了一下,看起来这是一个端点路由的错误,它有利于捕获所有路由,虽然它稍后被注册。

不幸的是,已知ASP.NET Core 2.2中的端点路由会破坏一些特殊情况,这就是为什么它正在针对3.0进行修改,这有望解决所有问题。话虽这么说,我打开了an issue about this particular problem并报告了我的发现。也许有一个简单的解决方案。

一个简单的解决方法是将settings/{controller}/{action}路径模板更改为使用除settings之外的前缀,这样就不再存在歧义。这似乎解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.