gpt4 book ai didi

ASP.NET Core 路由属性 - ID 和连字符 slug 以连字符分隔

转载 作者:行者123 更新时间:2023-12-02 15:45:47 25 4
gpt4 key购买 nike

我正在尝试通过 Route 属性为我的 Controller 操作之一配置以下 url 结构:

/products/12345-purest-green-widgets

这是我目前的路线:

[Route(@"/products/{id:int}-{slug:regex([[\w\-]]+)}")]
public ContentResult Show(int id, string slug)

这与预期路线不匹配,但确实匹配:

/products/12345-purest

并且还与一个单词后的尾随连字符匹配,一旦我添加其他任何内容,它就会不匹配。

有趣的是,如果我将字符串文字连字符(不是正则表达式的连字符)替换为/,它整体上工作正常:

[Route(@"/products/{id:int}/{slug:regex([[\w\-]]+)}")]
public ContentResult Show(int id, string slug)

匹配成功:

/products/12345/purest-green-widgets

所以它似乎被字符串文字连字符绊倒了。有什么想法吗?

最佳答案

如果深入挖掘,您会发现路由中间件正在贪婪地分割复杂的路由段,例如 {id:int}-{name:regex([[\w\-]]+)}甚至在应用路线约束之前。 (在启动中使用路由属性和路由表都会发生)

这意味着:

  • 网址如 products/123-foo ,路由匹配123作为 id 和 foo作为名字。然后它将应用约束,找到 123 的匹配项。是一个有效的 int 且 foo与正则表达式匹配。
  • 网址如 products/123-foo- ,路由匹配123作为 id 和 foo-作为名字。然后它将应用约束,再次找到匹配项。
  • 网址如 products/123-foo-bar ,路由匹配123-foo作为 id 和 bar作为名字。然后它将应用约束,但这一次它将失败,显示为 123-foo不是有效的整数!

如果您将参数拆分为不同的路线段(如 {id:int}/{name:regex([[\w\-]]+)} 所示),则不会出现此问题。 ,如/将按照您的预期正确分割参数。

如果您的路线确实需要具有该形状,那么我将在路线约束中使用单个参数。此参数将包装 id 和名称:

[Route(@"/products/{combined:regex(^[[\d]]+-[[\w\-]]+$)}")]

问题是您需要从该单个参数中手动提取 ID 和名称。

  • 您可以在 Controller 操作中手动执行此操作。对于一次性来说,这可能是可以接受的
  • 您可以创建一个 ActionFilter 并在执行操作之前将组合的路由参数拆分为操作参数(覆盖 OnActionExecuting )。这仍然很老套,特别是我的快速而肮脏的版本:

    public class SplitProductParametersActionFilter : ActionFilterAttribute
    {
    private static Regex combinedRegex = new Regex(@"^([\d]+)-([\w\-]+)$");
    public override void OnActionExecuting(ActionExecutingContext context)
    {
    var combined = context.RouteData.Values["combined"].ToString();
    var match = combinedRegex.Match(combined);
    if (match.Success)
    {
    context.ActionArguments.Add("id", int.Parse(match.Groups[1].Value));
    context.ActionArguments.Add("name", match.Groups[2].Value);
    }
    }
    }

    [Route(@"/products/{combined:regex(^[[\d]]+-[[\w\-]]+$)}")]
    [SplitProductParametersActionFilter]
    public IActionResult Contact(int id, string name)
    {
    }
  • 您可以使用其模型绑定(bind)程序提供程序和参数的一些注释属性创建一个新的模型绑定(bind)程序。这可能是最干净的,因为它与上面的方法类似,但以模型绑定(bind)的预期方式扩展了 MVC,但是我还没有时间探索它:

    [Route(@"/products/{combined:regex(^[[\d]]+-[[\w\-]]+$)}")]
    public IActionResult Contact([FromUrlProduct("combined")]int id, [FromUrlProduct("combined")]string name)
    {
    }
<小时/>

为了调试路由约束,您可以将日志记录设置为调试,并且您应该在控制台中看到类似这样的消息(您可能需要使用 dotnet run 从控制台运行应用程序,而不是使用 VS 中的 ISS ):

dbug: Microsoft.AspNetCore.Routing.RouteConstraintMatcher[1]
=> RequestId:0HKVJG96H1RQE RequestPath:/products/1-foo-bar
Route value '1-foo' with key 'id' did not match the constraint 'Microsoft.AspNetCore.Routing.Constraints.IntRouteConstraint'.

您还可以手动复制 int route constraint并在services.AddMvc()之后在启动中注册它与 services.Configure<RouteOptions>(opts => opts.ConstraintMap.Add("customint", typeof(CustomIntRouteConstraint)))

类似于 in this blog 所描述的方法也可能有助于调试。

关于ASP.NET Core 路由属性 - ID 和连字符 slug 以连字符分隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40009935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com