MVC Partial View表单提交未触发控制器HttpPost方法问题求助
问题描述
我有一个分部视图(Partial View),提交时应当触发控制器的HttpPost方法,但实际无法触发。主页面中引用该分部视图的代码如下:
<div class="box"> @Html.Action("AddNote", "Member", new { MemberId = Model.Id }) </div>
分部视图代码如下:
@model GMS.Core.Models.AddMemberNoteModel @using (Html.BeginForm("AddNote", "Member", FormMethod.Post)) { @Html.HiddenFor(model => model.MemberId) <div class="input-group"> @Html.EditorFor(model => model.Note, new { @class = "form-control", @placeholder = "Type note ..." }) @Html.ValidationMessageFor(model => model.Note) <span class="input-group-btn"> <input type="submit" class="btn btn-primary btn-flat" value="Save" /> </span> </div> }
问题表现为:点击提交按钮时,标记[HttpPost]的Action方法未被触发,页面加载时HttpGet的AddNote方法可以正常命中。控制器代码如下:
[Authorize] public ActionResult AddNote(string memberId) { AddMemberNoteModel model = new AddMemberNoteModel(); model.MemberId = Convert.ToInt32(memberId); return PartialView("AddNote", model); } [HttpPost] public ActionResult AddNote(AddMemberNoteModel model) { model.DateCreated = DateTime.Now; model.CreatedBy = ((CustomPrincipal)HttpContext.User).Id; model.LastUpdated = DateTime.Now; model.LastUpdateBy = ((CustomPrincipal)HttpContext.User).Id; if (ModelState.IsValid) { _memberService.AddNote(model); this.TempData["Notification"] = "A note has been added."; return RedirectToAction("Details", "Member", new { id = model.MemberId }); } else { return PartialView(model); } }
渲染后的HTML代码:
<form action="/Member/AddNote/7537" method="post"><input data-val="true" data-val-number="The field MemberId must be a number." data-val-required="The MemberId field is required." id="MemberId" name="MemberId" type="hidden" value="7537" /><div class="input-group"> <input class="text-box single-line" data-val="true" data-val-required="The Note field is required." id="Note" name="Note" type="text" value="" /> <span class="field-validation-valid" data-valmsg-for="Note" data-valmsg-replace="true"></span> <span class="input-group-btn"> <input type="submit" class="btn btn-primary btn-flat" value="Save" /> </span> </div> </form>
请问是什么原因导致该问题,该如何解决?
问题原因
- 路由参数匹配失败:ASP.NET MVC默认路由规则为
{controller}/{action}/{id},你渲染后的表单提交地址是/Member/AddNote/7537,路由系统会将最后一段的7537识别为id参数,但你的Post方法没有对应接收id参数,且Get方法的参数名是memberId,和路由默认参数名id不一致,导致Action选择器无法匹配到标记了[HttpPost]的AddNote方法。 - 表单嵌套冲突:如果主页面中存在外层表单嵌套了当前分部视图的表单,HTML规范不允许表单嵌套,会导致内层表单的提交行为失效,无法触发Post请求。
- 防伪验证拦截:如果你的项目全局开启了防伪令牌验证,或者Post方法上添加了
[ValidateAntiForgeryToken]特性,但表单内没有生成对应的防伪令牌隐藏域,请求会被框架直接拦截,无法进入Post方法。 - 前端JS拦截提交:如果页面内有JS代码监听了表单的submit事件,并且调用了
e.preventDefault()阻止了默认提交行为,也会导致请求没有发出,无法触发后端Post方法。
解决方案
对应上述原因,可选择以下方案修复:
- 修正路由参数匹配问题,二选一即可:
- 将Get方法的参数名改为和路由默认参数名一致:
// 把参数名从memberId改为id public ActionResult AddNote(string id) { AddMemberNoteModel model = new AddMemberNoteModel(); model.MemberId = Convert.ToInt32(id); return PartialView("AddNote", model); }- 显式指定表单提交的路由参数,修改分部视图的表单定义:
// 原来的写法 @using (Html.BeginForm("AddNote", "Member", FormMethod.Post)) // 修改为 @using (Html.BeginForm("AddNote", "Member", new { memberId = Model.MemberId }, FormMethod.Post)) - 排查HTML结构,确认没有外层表单嵌套当前分部视图的表单,如有嵌套调整页面结构移除嵌套即可。
- 如果项目开启了防伪验证,在表单内添加
@Html.AntiForgeryToken(),同时在Post方法上添加[ValidateAntiForgeryToken]特性即可。 - 检查页面内的JS代码,确认没有阻止表单默认提交的逻辑,如果是AJAX提交需求,对应调整JS逻辑即可。
内容的提问来源于stack exchange,提问作者dynmatt
相关产品推荐
相关产品推荐

