ASP.NET MVC中带HttpPost的同名控制器方法未被调用问题
ASP.NET MVC 路由匹配问题:无法触发带[HttpPost]的Details方法
我在开发一个集成Rest API的ASP.NET MVC项目时遇到了问题:控制器里有两个同名的Details方法,一个带[HttpPost]特性,另一个没有HTTP动词标注。但运行时总是调用无标注的那个,我想要触发带HttpPost的方法。
控制器代码示例
// GET: NormUserController/Details/5 public IActionResult Details(BankAccount account) { if (account != null) { Console.WriteLine("con" + account.IdUser); return View(account); } return RedirectToAction("Index"); } [HttpPost] public async Task<IActionResult> Details(int IdAccount) { Console.WriteLine("starting post"); var account = await servicio_APIBAccount.Obtener(IdAccount); Console.WriteLine("Account: " + account.IdAccount); if (account != null) { Console.WriteLine("Id Account " + account.IdAccount); return View("Edit", account); } Console.WriteLine("Failed"); return RedirectToAction("Index"); }
对应的Razor视图代码
@model BankAccount @{ ViewData["Title"] = "Estado de cuenta"; } <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> <link href="~/css/site.css" rel="stylesheet"> <div class="card" style="width: 18rem;"> <h2>@ViewData["Title"]</h2> <div class="card-body"> <h4>Cuenta de ahorro</h4> <table class="table table-borderless"> <tr> <td>Número de cuenta:</td> <td></td> <td></td> <td>@Model.AccountNumber</td> </tr> <tr> <td>Saldo disponible:</td> <td></td> <td></td> <td>$@Model.AccountAmount</td> </tr> </table> </div> </div> <div> <a asp-action="Details" asp-controller="NormUser" class="button button-accion">Transferencias</a> <a asp-action="Index" asp-controller="Home" class="button cerrar-sesion">Cerrar Sesión</a> </div>
问题原因及解决办法
核心原因
视图里的"Transferencias"按钮用的是<a>标签,这类标签默认发送GET请求,而ASP.NET MVC中无HTTP动词标注的方法默认接受GET请求,所以会匹配到不带[HttpPost]的Details方法;带[HttpPost]的方法只接受POST请求,自然不会被触发。
解决步骤
方法一:改用表单提交(推荐)
把<a>标签替换成表单,通过POST请求触发目标方法,同时传递必要参数:
<div> <form asp-action="Details" asp-controller="NormUser" method="post"> <input type="hidden" name="IdAccount" value="@Model.IdAccount" /> <button type="submit" class="button button-accion">Transferencias</button> </form> <a asp-action="Index" asp-controller="Home" class="button cerrar-sesion">Cerrar Sesión</a> </div>
点击按钮时会发送POST请求,匹配到带[HttpPost]的Details方法,隐藏字段会把当前账户的IdAccount传递过去。
方法二:给GET方法显式添加[HttpGet]特性
虽然不能直接解决POST触发问题,但能让路由规则更清晰,避免歧义:
[HttpGet] public IActionResult Details(BankAccount account) { // 原有代码逻辑 }
方法三:用AJAX发送POST请求(无刷新场景)
如果需要页面无刷新提交,可以用AJAX实现:
@Html.AntiForgeryToken() <div> <button class="button button-accion" data-id="@Model.IdAccount">Transferencias</button> <a asp-action="Index" asp-controller="Home" class="button cerrar-sesion">Cerrar Sesión</a> </div> <script> document.querySelector('.button-accion').addEventListener('click', function(e) { e.preventDefault(); const id = this.getAttribute('data-id'); fetch('/NormUser/Details', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }, body: `IdAccount=${id}` }).then(response => { if (response.ok) { window.location.href = response.url; } }); }); </script>
注意要添加防伪令牌(@Html.AntiForgeryToken()),避免跨站请求伪造。
额外提示
确保POST方法需要的IdAccount参数能正确传递,比如从当前视图的Model中获取,否则会导致参数为空,影响后续的API调用逻辑。
内容的提问来源于stack exchange,提问作者DaSe
相关产品推荐
相关产品推荐

