C# ASP.NET Core 2.2中的终结点路由无效

C# ASP.NET Core 2.2中的终结点路由无效,c#,asp.net-core,routing,asp.net-core-2.2,C#,Asp.net Core,Routing,Asp.net Core 2.2,更新(2) @poke似乎已经弄明白了这一点,如果对其他更高的路由存在明显的模糊性,那么端点路由本身就有利于{*url} 更新(1) @poke评论说我在{*url}路径上有一个输入错误,在那里缺少t-in控制器。修复后,{*url}路由开始工作,DefaultController.Gone操作正在工作 但是现在奇怪的行为又开始出现了。在修复{*url}后,导航到/settings,该设置应与{controller}/{action}路由匹配,但失败并返回到{*url}路由 如果我从注册中删除{

更新(2)

@poke似乎已经弄明白了这一点,如果对其他更高的路由存在明显的模糊性,那么端点路由本身就有利于
{*url}

更新(1)

@poke评论说我在
{*url}
路径上有一个输入错误,在那里缺少t-in控制器。修复后,
{*url}
路由开始工作,
DefaultController.Gone
操作正在工作

但是现在奇怪的行为又开始出现了。在修复
{*url}
后,导航到
/settings
,该设置应与
{controller}/{action}
路由匹配,但失败并返回到
{*url}
路由

如果我从注册中删除
{*url}
路由,那么
/settings
将再次工作。
{action}
路由继续不工作

原创

<h1>TOOLS.DEFAULT</h1>
<!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>
请原谅问题的长度,但我正试图提供尽可能多的信息

我正在为自己开发一个ASP.NETCore2.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();
}
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"
                });
            });
    }
}
public sealed class CategoriesController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Category added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Category {id} removed");
}
public sealed class DefaultController :
    Controller {
    [HttpGet]
    public IActionResult About() => View();

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

    [HttpGet]
    public IActionResult Show(
        string slug) => View();
}
<h1>POSTS.LIST</h1>
<a asp-action="Show" asp-controller="Posts" asp-route-slug="test-test-test">Show a Post</a>
<h1>POSTS.SHOW</h1>
public sealed class SettingsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
<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>
public sealed class TagsController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Tag added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Tag {id} removed");
}
public sealed class ToolsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
CategoriesController.cs

public sealed class Program {
    public static async Task Main(
        string[] args) => await WebHost.CreateDefaultBuilder(args)
                                       .UseStartup<Startup>()
                                       .Build()
                                       .RunAsync();
}
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"
                });
            });
    }
}
public sealed class CategoriesController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Category added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Category {id} removed");
}
public sealed class DefaultController :
    Controller {
    [HttpGet]
    public IActionResult About() => View();

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

    [HttpGet]
    public IActionResult Show(
        string slug) => View();
}
<h1>POSTS.LIST</h1>
<a asp-action="Show" asp-controller="Posts" asp-route-slug="test-test-test">Show a Post</a>
<h1>POSTS.SHOW</h1>
public sealed class SettingsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
<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>
public sealed class TagsController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Tag added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Tag {id} removed");
}
public sealed class ToolsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
DefaultController.cs

public sealed class Program {
    public static async Task Main(
        string[] args) => await WebHost.CreateDefaultBuilder(args)
                                       .UseStartup<Startup>()
                                       .Build()
                                       .RunAsync();
}
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"
                });
            });
    }
}
public sealed class CategoriesController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Category added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Category {id} removed");
}
public sealed class DefaultController :
    Controller {
    [HttpGet]
    public IActionResult About() => View();

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

    [HttpGet]
    public IActionResult Show(
        string slug) => View();
}
<h1>POSTS.LIST</h1>
<a asp-action="Show" asp-controller="Posts" asp-route-slug="test-test-test">Show a Post</a>
<h1>POSTS.SHOW</h1>
public sealed class SettingsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
<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>
public sealed class TagsController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Tag added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Tag {id} removed");
}
public sealed class ToolsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
About.cshtml(默认)

List.cshtml(Posts)

Default.cshtml(设置)

ToolsController.cs

public sealed class Program {
    public static async Task Main(
        string[] args) => await WebHost.CreateDefaultBuilder(args)
                                       .UseStartup<Startup>()
                                       .Build()
                                       .RunAsync();
}
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"
                });
            });
    }
}
public sealed class CategoriesController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Category added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Category {id} removed");
}
public sealed class DefaultController :
    Controller {
    [HttpGet]
    public IActionResult About() => View();

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

    [HttpGet]
    public IActionResult Show(
        string slug) => View();
}
<h1>POSTS.LIST</h1>
<a asp-action="Show" asp-controller="Posts" asp-route-slug="test-test-test">Show a Post</a>
<h1>POSTS.SHOW</h1>
public sealed class SettingsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
<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>
public sealed class TagsController :
    Controller {
    [HttpGet]
    public IActionResult Add() => Content("Tag added");

    [HttpGet]
    public IActionResult Remove(
        int id) => Content($"Tag {id} removed");
}
public sealed class ToolsController :
    Controller {
    [HttpGet]
    public IActionResult Default() => View();
}
Default.cshtml

<h1>TOOLS.DEFAULT</h1>
<!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>
TOOLS.DEFAULT
\u Layout.cshtml

<h1>TOOLS.DEFAULT</h1>
<!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>

@视图包。标题
博客

工具
关于
设置
@RenderBody()
{action}
-不起作用

这一个不起作用,因为它必须与实际行动相匹配。因此,它适用于
/Show
/List
,因为您正在
PostsController
上操作。它也适用于
/
,因为
操作
默认为
列表

{*url}
-不起作用

如果您设置默认的
控制器
,而不是
控制器
,则此选项将起作用:

r.MapRoute("-1", "{*url}", new
{
    action = "Gone",
    controller = "Default"
});
并报告了我的发现。也许有一个简单的解决办法


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

conroller=“Default”
–有一个打字错误,缺少
t
。这能解决问题吗@poke,谢谢,它修复了
{*url}
路由,但是
{action}
路由仍然没有生成。奇怪的是,本应与
{controller}/{action}
路由匹配的
/settings
现在失败,并返回到
{*url}
路由。如果我从注册中删除
{*url}
路由,那么
/settings
将再次工作。我开始回忆起原始项目中的怪异行为:(我想我开始明白了。自从
{action}
route有一个默认的控制器
Posts
我在标记帮助器中指定控制器并不重要,因为即使我想要
default.About
,生成的路由将是
Posts.About
,并且由于操作不存在,链接为空。添加属性修复了这一点,因此我会让步。这尽管如此,
{*url}
导航到
/settings
还是一个令人困惑的问题。我决定删除
{action}
路由注册,并为
博客”添加了一个属性
PostsController.List
action上,它包括根URL和
/blog
URL。我仍然不明白为什么
/settings
路由到
{*URL}
路由,而
{controller}/{action}
路由应该首先基于约束(和注册顺序)匹配。它适用于
/tools
。删除
{*url}
路由将修复
/settings
。是否可以猜测其为何会出现这种行为?“即使我想要默认值。关于,生成的路由将是Posts.About”–这并不完全正确。路由的工作方式是,它为前面的所有端点生成URL,因此它已经知道使用哪个路由,例如
PostsC