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时,会优先匹配参数数量更少、结构更简单的路由模板,同时结合参数名称匹配度选择模板:
- 当传入
ID1和ID2两个参数时,路由系统遍历Redirected的模板,第一个模板{ID1}/Redirected仅需匹配一个参数ID1,系统会优先选中它——把ID1赋值为传入的b,剩余的ID2=a因找不到对应路由参数,被追加为查询字符串。 - 第二个模板
{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"; }
方式二:指定路由名称
给每个路由模板设置唯一名称,在重定向时指定目标路由名称,强制匹配:
- 给路由添加名称:
[Route("{ID1}/Redirected", Name = "Redirected_SingleId")] [Route("{ID2}/{ID1}/Redirected", Name = "Redirected_DoubleId")] public string Redirected() { return "Redirected"; }
- 根据参数是否存在选择对应路由:
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
相关产品推荐
相关产品推荐

