如何在ASP.NET Core多控制器中复用表单提交方法并处理验证错误?
复用表单提交方法并保留原URL的解决方案
方案一:改进控制器继承逻辑,动态返回原视图
1. 修改分部视图的表单目标
把表单的asp-controller改为当前页面所在的控制器,不要写死Base:
@model UserModel <form asp-controller="@ViewContext.RouteData.Values["controller"]" asp-action="ScheduleDemo" method="post" asp-antiforgery="true"> <p> <label asp-for="@Model.UserName">UserName</label><br /> <input type="text" asp-for="@Model.UserName" /> <span asp-validation-for="UserName" class="text-danger" style="color: red;"></span> </p> <p> <label asp-for="@Model.Age">Age</label><br /> <input asp-for="@Model.Age" /> <span asp-validation-for="Age" class="text-danger" style="color: red;"></span> </p> <p> <label asp-for="@Model.City">City</label><br /> <input type="text" asp-for="@Model.City" /> </p> <input type="submit" value="Send" /> </form>
这样表单会提交到当前页面的控制器(Home/Additional),不会跳转到Base的路由。
2. 优化BaseController的提交方法
验证失败时返回当前控制器的Index视图,保留原URL的同时传递错误模型:
public class BaseController : Controller { [HttpPost] public IActionResult ScheduleDemo(UserModel model) { if (ModelState.IsValid) { // 执行邮件发送等业务逻辑 // 成功后重定向回原页面,避免表单重复提交 return RedirectToAction("Index", ControllerContext.ActionDescriptor.ControllerName); } // 验证失败,返回当前控制器的Index视图,错误模型会自动传递给分部视图 return View("Index", model); } }
由于Home和Additional都继承自Base,ControllerContext.ActionDescriptor.ControllerName会自动获取当前控制器名称,返回对应视图后URL保持不变,分部视图能正常显示验证错误。
方案二:AJAX无刷新提交(体验更优)
如果希望页面不刷新,仅更新表单区域,可采用AJAX提交:
1. 修改分部视图添加AJAX逻辑
@model UserModel <div id="scheduleDemoContainer"> <form id="demoForm" asp-antiforgery="true"> <p> <label asp-for="@Model.UserName">UserName</label><br /> <input type="text" asp-for="@Model.UserName" /> <span asp-validation-for="UserName" class="text-danger" style="color: red;"></span> </p> <p> <label asp-for="@Model.Age">Age</label><br /> <input asp-for="@Model.Age" /> <span asp-validation-for="Age" class="text-danger" style="color: red;"></span> </p> <p> <label asp-for="@Model.City">City</label><br /> <input type="text" asp-for="@Model.City" /> </p> <input type="submit" value="Send" /> </form> </div> @section Scripts { <script> $(document).ready(function() { $("#demoForm").submit(function(e) { e.preventDefault(); var formData = $(this).serialize(); var submitUrl = '@Url.Action("ScheduleDemo")'; $.post(submitUrl, formData) .done(function() { alert("提交成功"); $("#demoForm")[0].reset(); }) .fail(function(xhr) { // 验证失败时,用返回的分部视图替换原表单区域 $("#scheduleDemoContainer").html(xhr.responseText); }); }); }); </script> }
2. 调整BaseController方法
验证失败返回分部视图,成功返回状态提示:
public class BaseController : Controller { [HttpPost] public IActionResult ScheduleDemo(UserModel model) { if (ModelState.IsValid) { // 执行业务逻辑 return Ok(); } // 验证失败返回带错误模型的分部视图 return PartialView(@"~/Views/Shared/Partial/ScheduleDemo.cshtml", model); } }
这种方式完全避免页面跳转,仅更新表单区域,同时实现代码复用。
补充提示
- 确保
UserModel配置了正确的验证特性(如[Required]、[Range]等),才能让ModelState正确捕获错误。 - 方案一中的重定向逻辑可根据需求调整,比如用
TempData传递成功提示信息。
内容的提问来源于stack exchange,提问作者Artem Mazurov
相关产品推荐
相关产品推荐

