ASP.NET Core MVC中如何将GET模型参数传递至POST方法?
解决方案
针对ASP.NET Core MVC中POST方法无法获取GET视图模型原有属性的问题,有以下几种实用方案:
方案1:通过隐藏输入字段传递模型属性
表单提交时只会发送表单内的控件数据,因此可以把需要保留的UserViewModel属性以隐藏字段的形式嵌入表单中,这样POST方法就能完整接收模型数据。
在表单内部添加以下隐藏字段(放在展示代码之后、密码输入框之前即可):
<form asp-controller="Profiles" asp-action="Index" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="mt-4 pt-2 needs-validation" role="form" novalidate> <h5>@Model.Username</h5> <p>@Model.Roles<br/>@Model.Email</p> <!-- 添加隐藏字段传递原有模型属性 --> <input asp-for="Username" type="hidden" /> <input asp-for="NameAbbrv" type="hidden" /> <input asp-for="Roles" type="hidden" /> <input asp-for="Email" type="hidden" /> <input asp-for="ChangePassword.OldPassword" class="form-control" id="currentPassword" required autofocus /> <input asp-for="ChangePassword.NewPassword" id="newPassword" class="form-control" required /> </form>
注意:如果属性包含敏感信息,不建议使用此方案(前端可篡改隐藏字段值)。
方案2:封装公共方法避免代码冗余
将GET方法中获取用户信息的逻辑抽成私有方法,让GET和POST方法共享调用,既避免冗余,又能保证数据是最新的(从数据库重新获取,不受前端篡改影响)。
步骤1:封装获取用户视图模型的私有方法
在控制器中添加以下方法:
private async Task<UserViewModel> GetCurrentUserViewModel() { var userEmail = User.FindFirstValue(ClaimTypes.Name); var currentUser = await _userManager.FindByEmailAsync(userEmail); var roles = await _userManager.GetRolesAsync(currentUser); return new UserViewModel { Username = $"{currentUser.FirstName} {currentUser.LastName}", NameAbbrv = $"{currentUser.FirstName[..1]}{currentUser.LastName[..1]}", Roles = string.Join(", ", roles), Email = currentUser.Email }; }
步骤2:改造GET和POST方法
// GET方法 [HttpGet] public async Task<IActionResult> Index() { var userViewModel = await GetCurrentUserViewModel(); return View(userViewModel); } // POST方法 [HttpPost] public async Task<IActionResult> Index(UserViewModel model) { if (!ModelState.IsValid) { // 验证失败时,重新填充用户基本信息,保留提交的密码表单数据 var userViewModel = await GetCurrentUserViewModel(); userViewModel.ChangePassword = model.ChangePassword; return View(userViewModel); } // 执行修改密码的业务逻辑(示例) var currentUser = await _userManager.FindByEmailAsync(model.Email); var result = await _userManager.ChangePasswordAsync(currentUser, model.ChangePassword.OldPassword, model.ChangePassword.NewPassword); if (result.Succeeded) { // 密码修改成功,返回更新后的用户视图模型 return View(await GetCurrentUserViewModel()); } // 密码修改失败,添加错误信息并返回原视图 foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } var errorUserViewModel = await GetCurrentUserViewModel(); errorUserViewModel.ChangePassword = model.ChangePassword; return View(errorUserViewModel); }
方案3:使用TempData临时存储模型(适合重定向场景)
如果POST后需要重定向到其他页面,可以用TempData临时存储视图模型,但需注意TempData是一次性的,且需要序列化对象:
GET方法中存储模型
[HttpGet] public async Task<IActionResult> Index() { var userViewModel = await GetCurrentUserViewModel(); TempData["UserViewModel"] = JsonSerializer.Serialize(userViewModel); return View(userViewModel); }
POST方法中读取模型
[HttpPost] public async Task<IActionResult> Index(UserViewModel model) { if (!ModelState.IsValid) { var json = TempData["UserViewModel"] as string; var userViewModel = JsonSerializer.Deserialize<UserViewModel>(json); userViewModel.ChangePassword = model.ChangePassword; TempData.Keep("UserViewModel"); // 保留数据以便再次使用 return View(userViewModel); } // 处理密码修改逻辑... return RedirectToAction(nameof(Index)); }
内容的提问来源于stack exchange,提问作者Jesus
相关产品推荐
相关产品推荐

