繁体   English   中英

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

[英]Endpoint Routing in ASP.NET Core 2.2 is Not Working

更新(2)

@poke似乎已经解决了这个问题,并且如果端点路由本身支持{*url}似乎与其他更高的路由存在歧义,这似乎是一个问题。

更新(1)

@poke评论说我在{*url}路线上有错字,而控制器中的t丢失了。 修复{*url}路由开始起作用并且DefaultController.Gone操作起作用之后。

但! 现在,奇怪的行为开始再次出现。 修复{*url}后,导航至/settings应该与{controller}/{action}路由匹配的{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因为其中同时包含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>

{action} -不起作用

此操作无效,因为它必须匹配实际操作。 因此,由于您在PostsController上进行操作,因此它适用于/Show/List 由于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 ,因此路由不匹配。 您将需要调整约束条件或添加其他路线才能使其生效。

顺便说一句。 作为一般建议:您可能已经注意到,管理这么多的路由映射变得相当复杂。 仅将属性路由与显式路由一起使用通常会更容易。 您也可以将它们与基于模板的路由结合使用,以充分利用两者的优势。


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

合并settings/{controller}/{action}{controller}/{action=Default}路由似乎是一个副作用。

我已经进行了一段时间的调试,这似乎是端点路由的一个错误,尽管以后要注册,但它倾向于捕获所有路由。

不幸的是,已知ASP.NET Core 2.2中的终结点路由会在一些特殊情况下中断,这就是为什么将其修改为3.0,从而有望解决所有问题的原因。 话虽如此,我已经打开了一个有关此特定问题的问题并报告了我的发现。 也许有一个简单的解决方案。

一种简单的解决方法是将settings/{controller}/{action}路由模板更改为使用settings以外的前缀,这样就不再存在歧义。 看来可以解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM