You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core中RedirectToAction路由匹配异常生成查询串问题排查

问题描述

在使用Post-Redirect-Get模式时,遇到RedirectToAction的路由匹配异常,示例代码如下:

public class TestController : Controller
{
    [Route("{ID1}/Test")]
    [Route("{ID2}/{ID1}/Test")]
    public IActionResult Test(string id1, string id2)
    {
        return RedirectToAction("Redirected", new { ID1 = id1, ID2 = id2 });
    }

    [Route("{ID1}/Redirected")]
    [Route("{ID2}/{ID1}/Redirected")]
    public string Redirected()
    {
        return "Redirected";
    }
}

请求/a/test时,正常重定向到/a/Redirected;但请求/a/b/test时,实际重定向到/b/Redirected?ID2=a,而非预期的/a/b/Redirected。即使调整路由定义顺序,结果也不变。

补充:若将动作名称改为令牌{action},则能匹配预期路由:

[Route("{ID1}/{action}")]
[Route("{ID2}/{ID1}/{action}")]
public string Redirected()
{
    return "Redirected";
}
原因分析

ASP.NET Core路由生成URL时,会优先匹配参数数量更少、结构更简单的路由模板,同时结合参数名称匹配度选择模板:

  1. 当传入ID1和ID2两个参数时,路由系统遍历Redirected的模板,第一个模板{ID1}/Redirected仅需匹配一个参数ID1,系统会优先选中它——把ID1赋值为传入的b,剩余的ID2=a因找不到对应路由参数,被追加为查询字符串。
  2. 第二个模板{ID2}/{ID1}/Redirected虽需要两个参数,但因为第一个模板的静态后缀Redirected直接匹配动作名,结构更简单,所以优先级更高。

而使用{action}令牌时,路由模板的结构是{ID1}/{action}和{ID2}/{ID1}/{action},action会被替换为Redirected,此时路由系统会根据传入的参数数量(两个)自动匹配对应模板,生成正确URL。

解决方案

有三种可靠方式实现预期路由匹配:

方式一:使用{action}令牌(推荐)

如补充说明中的写法,让路由模板通过{action}动态匹配动作名称,路由系统会根据参数数量自动选择对应模板:

[Route("{ID1}/{action}")]
[Route("{ID2}/{ID1}/{action}")]
public string Redirected()
{
    return "Redirected";
}

方式二:指定路由名称

给每个路由模板设置唯一名称,在重定向时指定目标路由名称,强制匹配:

  1. 给路由添加名称:
[Route("{ID1}/Redirected", Name = "Redirected_SingleId")]
[Route("{ID2}/{ID1}/Redirected", Name = "Redirected_DoubleId")]
public string Redirected()
{
    return "Redirected";
}
  1. 根据参数是否存在选择对应路由:
public IActionResult Test(string id1, string id2)
{
    if (string.IsNullOrEmpty(id2))
    {
        return RedirectToRoute("Redirected_SingleId", new { ID1 = id1 });
    }
    else
    {
        return RedirectToRoute("Redirected_DoubleId", new { ID1 = id1, ID2 = id2 });
    }
}

方式三:设置路由优先级

通过Order属性指定路由优先级(值越小优先级越高),让双参数模板优先被匹配:

[Route("{ID1}/Redirected", Order = 2)]
[Route("{ID2}/{ID1}/Redirected", Order = 1)]
public string Redirected()
{
    return "Redirected";
}

这种方式无需修改重定向逻辑,路由系统会优先选择Order值更小的双参数模板,生成正确URL。

内容的提问来源于stack exchange,提问作者Scuzzlebutt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:25:28