我认为URL生成有问题。
假设我们有以下控制器:
[Route("[action]")]
public class Home : Controller
{
[Route("/")]
public IActionResult Index()
{
return View();
}
[HttpGet]
[Route("{number}")]
public IActionResult Edit(int number)
{
return View();
}
[HttpPost]
public IActionResult Edit()
{
return View();
}
}
索引视图生成了指向“编辑”操作的正确链接:
<a asp-action="Edit" asp-all-route-data='new Dictionary<string, string>{{"number", "11"}}'>GO TO EDIT</a>
也就是/Edit/11
但是在编辑视图中,我试图创建一个表单,它应该发布到相同的action,但是没有路由参数。所以,URL应该只是/Edit
。相反,我得到了/Edit/11
,它没有到达控制器上的适当action。我用两种方式生成表单,结果是一样的:
<div>
<form asp-action="Edit" method="post">
<button type="submit">submit</button>
</form>
@using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
<button type="submit">submit</button>
}
</div>
此外,将POST路由模板更改为:
[HttpPost]
[Route("something")]
public IActionResult Edit()
{
return View();
}
导致为GET生成的链接为http://localhost:5253/Edit/something?number=11
,这是错误的。
对我来说,它看起来像一个bug,但我可能忽略了一些东西。你能帮助我理解这种行为吗?所有端点都正确注册了。是否涉及路由优先级?如果是,那么如何因为那些动作方法对单独的动词做出React...我很困惑。
请在此链接下找到项目:https://blindsend.io#5m4QCCyXKdchLEos4M1ang;GnFBHbs2xAap6QzxJadwFw==
2条答案
按热度按时间bfrts1fy1#
我对你的示例代码进行了测试,在我注解了
[Route("{number}")]
之后,一切都运行得很好。当我们在Get action方法之前有
[Route("{number}")]
时,对Controller的请求将是https://localhost:7131/Edit/11
,如果我们注解此属性,则请求将是https://localhost:7131/Edit?number=11
。错误发生在表单提交操作中,对于POST操作
public IActionResult Edit()
,正确的请求URL应该是POST https://localhost:7131/Edit
,但当浏览器中的URL是https://localhost:7131/Edit/11
并进行表单提交时,提交请求将如下所示,问题发生了。关于错误405,这意味着URL是正确的,但方法是不允许的,在这个问题中,“不允许”指向Url Routing,为了修复问题,我们可以注解
[Route("{number}")]
或将[Route("{number}")]
添加到POST操作中。让我们回到正常的行为,在这里看到official sample。默认的路由Map定义为
pattern: "{controller=Home}/{action=Index}/{id?}");
,当Edit Get请求变成Movies/Edit/5
时,我们需要让Movie Controller具有Get操作public async Task<IActionResult> Edit(int? id)
,id
是参数而不是路由属性。这就是为什么我说我在开头注解了[Route("{number}")]
。xtupzzrd2#
顺便说一句,你可以在GitHub上的这个问题中找到aspnet团队的答案:https://github.com/dotnet/aspnetcore/issues/47375#issuecomment-1481063287