【问题标题】:How to use ambient route values in ASP.NET Core 3 Razor Pages?如何在 ASP.NET Core 3 Razor Pages 中使用环境路由值?
【发布时间】:2020-06-27 03:35:51
【问题描述】:

使用 ASP.NET Core 3 Razor 页面,假设您要设置具有以下 URL 结构的页面:

http://contoso.com/course/4231/details
http://contoso.com/course/4231/students

其中 4231 是课程 ID。这可以通过使用@page 指令来实现:

@page "/course/{courseId}/details"

现在假设您要在/details/students 页面之间创建链接。然后,您希望将courseId 参数添加到每个链接,这可以使用锚标记助手完成,如下所示:

<a asp-page="./students" asp-route-courseid="@RouteData.Values["courseId"]>Students</a>

据我了解,在 ASP.NET Core 2.1 及更早版本中,没有必要为此添加 asp-route-* 属性,因为路由值会“传播”到其他页面,并自动添加到任何锚标记,除非手动覆盖(“环境路由值”,因为它被称为)。这显然在 2.2 版中被删除了,但我不太清楚为什么。

必须始终记住使用上述方案手动传播路由值似乎是一个非常容易出错的工作流程,如果您有许多始终需要添加到锚标记的路由值,可能会很快失控。

是否可以在更高版本的 ASP.NET Core 中手动启用环境路由值,至少对于单个参数?有什么理由不这样做吗?

基本上,我希望锚标记助手是相对的,以便从/course/4231/details 链接到./students 会自动解析为/course/4231/details

【问题讨论】:

  • 您好,Patrik,欢迎来到 Stack Overflow。我不知道答案,但我想承认这是一个有趣且很好沟通的问题。这是一个非常好的第一篇文章。如果有人知道答案,我会很好奇,因为我同意这对于在当前路线和目标路线之间共享路线数据的情况下是一个有用的功能。
  • 嘿,非常感谢!我同意这将是一个非常有用的功能,事实上我有点惊讶它没有以这种方式工作,尤其是当您将路由值放在 url 中而不是作为查询参数时。对我来说,查询参数被重置是有意义的,因为它们对于每个页面来说通常是不同的,但是作为 URL 一部分的值通常代表页面层次结构中的一个级别,所以不为相对链接自动设置它们似乎很奇怪.

标签: c# asp.net asp.net-core razor-pages


【解决方案1】:

IMO,这是意料之中的。当您重定向到相同的操作/页面时,当前的环境路由值正在被重用。

<a asp-page="details">Studentdetails</a>

它生成url:/course/4231/details

当您重定向到不同的操作/页面时,环境值会被正确忽略。

<a asp-page="./students">Students</a>

它不会生成正确的 url。

参考https://github.com/dotnet/aspnetcore/issues/3746

【讨论】:

  • 是的,正如你所说,这似乎是框架中的设计。但是,我感兴趣的是在重定向到其他操作或页面时是否可以(通过选择)保持环境值。这将使管理动态页面层次结构变得更加容易。不过谢谢!
【解决方案2】:

既然我设法找到了解决方案,我将回答我自己的问题。

正如this GitHub issue(感谢 Oliver Weichhold)中所述,您可以覆盖默认的锚标记助手(和表单操作标记助手),以实现将路由值自动添加到链接的所需行为。

我最终实现了标签助手的派生版本,如果它们是路由模板的一部分,它将自动添加路由值,因为这是我正在寻找的行为。为了简短起见,标签助手的 Process 方法如下所示:

public override void Process(TagHelperContext context, TagHelperOutput output)
{
    var routeTemplate = ViewContext.ActionDescriptor.AttributeRouteInfo.Template;

    Regex regex = new Regex(@"\{(\w+)(:.+)?\??\}");
    var matches = regex.Matches(routeTemplate);

    if (matches.Count > 0)
        foreach (var routeValueKvp in ViewContext.HttpContext.Request.RouteValues)
            if (matches.Any(x => x.Groups[1].Value == routeValueKvp.Key))
                RouteValues[routeValueKvp.Key] = routeValueKvp.Value.ToString();

    base.Process(context, output);
}

此解决方案有效,但不是最佳的。原因之一是自定义标签助手需要手动装饰 HtmlTargetElement 属性,这意味着如果标签助手的基本版本在框架的未来版本中使用新属性进行扩展,自定义版本将需要手动更新。

【讨论】:

    猜你喜欢
    • 2018-02-17
    • 2020-10-27
    • 2019-07-05
    • 1970-01-01
    • 2018-10-29
    • 2022-07-14
    • 2018-03-17
    • 2019-03-25
    • 2018-06-24
    相关资源
    最近更新 更多