ASP.NET Core MVC自定义用户资料编辑功能异常求助(非Identity)
ASP.NET Core MVC 用户资料编辑功能异常(未使用Identity框架)
问题概述
我正在为ASP.NET Core MVC项目添加现有用户资料编辑功能,未使用Identity框架,但功能存在异常,当前报错为Id的验证状态无效(Invalid validation state for Id)。
相关代码
Users模型
public partial class Users { [Key] public Guid Id { get; set; } [Display(Name = "Name")] public string Name { get; set; } //email [Required(ErrorMessage = "Enter Your Email..")] [Display(Name = "Email")] public string Email { get; set; } //username [Required(ErrorMessage = "Enter Username..")] [Display(Name = "Username")] public string Username { get; set; } //password [Required(ErrorMessage = "Enter Password...")] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } //confirm [Required(ErrorMessage = "Confirm...")] [DataType(DataType.Password)] [Display(Name = "Confirm Password")] [Compare("Password")] public string ConfirmPass { get; set; } }
UsersController控制器
public class UsersController : Controller { private readonly TAContext _context; public UsersController(TAContext context) { _context = context; } public IActionResult Index() { return View(); } public IActionResult Create() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult Create([Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc) //register users { _context.Add(uc); _context.SaveChanges(); //return RedirectToAction("Edit", "Users"); return View(uc); //uc? } [Authorize] public async Task<IActionResult> Edit(Guid? id) { var ucc = await _context.Users.FindAsync(id); return View(ucc); } [HttpPost] public async Task<ActionResult> Edit(Guid id, [Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc) //register users { //if (ModelState.IsValid) //{ // _context.Entry(uc).State = EntityState.Modified; // await _context.SaveChangesAsync(); // return RedirectToAction("Index"); //} //_context.Update(uc); //await _context.SaveChangesAsync(); //return View(uc); if (id != uc.Id) { return NotFound(); } if (ModelState.IsValid) { try { _context.Update(uc); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!UserExists(uc.Id)) { return NotFound(); } else { throw; } } return RedirectToAction("Login", "Logusers"); } return View(uc); } private bool UserExists(Guid id) { return _context.Users.Any(e => e.Id == id); } }
编辑视图
@model TA.Models.Users @{ ViewData["Title"] = "Edit"; } <div class=" container2"> <hr /> <h1>User edit</h1> <hr /> <div class="row"> <div class="col-md-4"> <form asp-action="Edit"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input type="hidden" asp-for="Id" /> <div class="form-group"> <label asp-for="Name" class="control-label"></label> <input asp-for="Name" class="form-control" placeholder="Name" /> <span asp-validation-for="Name" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Username" class="control-label"></label> <input asp-for="Username" class="form-control" placeholder="Username" /> <span asp-validation-for="Username" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Password" class="control-label"></label> <input asp-for="Password" class="form-control" type="password" placeholder="Password" /> <span asp-validation-for="Password" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="ConfirmPass" class="control-label"></label> <input asp-for="ConfirmPass" class="form-control" type="password" placeholder="Confirm Password" /> <span asp-validation-for="ConfirmPass" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Email" class="control-label"></label> <input asp-for="Email" class="form-control" placeholder="Email" /> <span asp-validation-for="Email" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Save User Details" class="btn btn-primary" /> </div> <span class="text-danger">@ViewBag.message</span> </form> </div> </div> <div> <a asp-controller="Home" asp-action="Index" class="return-to-hp">Back to Homepage</a> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
问题原因分析
- 新增用户时Id未正确生成:Guid类型主键默认不会自动生成(除非配置
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]),原Create方法未手动生成Guid,导致用户Id可能为空,后续编辑时触发验证错误。 - Id字段的不必要验证:编辑时Id作为隐藏字段传递,但ModelState会对Guid类型进行默认验证,路由Id与模型Id匹配时易出现异常。
- 密码字段的强制验证:编辑时模型仍保留Password和ConfirmPass的
[Required]属性,若用户不想修改密码,空值会触发验证错误,进而影响整体ModelState有效性,间接引发Id的验证提示。
解决方案
1. 修复用户新增时的Id生成
修改Create方法,手动生成Guid并添加ModelState验证:
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Create([Bind("Name,Email,Username,Password,ConfirmPass")] Users uc) { uc.Id = Guid.NewGuid(); // 生成有效Guid if (ModelState.IsValid) { _context.Add(uc); _context.SaveChanges(); return RedirectToAction("Index"); } return View(uc); }
2. 移除编辑时Id的验证错误
在Edit的HttpPost方法中,判断ModelState之前手动移除Id的验证条目:
[HttpPost] [ValidateAntiForgeryToken] // 添加上防CSRF验证 public async Task<IActionResult> Edit(Guid id, [Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc) { if (id != uc.Id) { return NotFound(); } // 移除Id的验证,因为主键无需验证输入 ModelState.Remove("Id"); if (ModelState.IsValid) { try { _context.Update(uc); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!UserExists(uc.Id)) { return NotFound(); } else { throw; } } return RedirectToAction("Login", "Logusers"); } return View(uc); }
3. 优化模型,使用ViewModel分离场景
创建专门的编辑视图模型,移除密码字段的[Required](或根据需求保留),避免不必要的验证:
public class EditUserViewModel { public Guid Id { get; set; } [Display(Name = "Name")] public string Name { get; set; } [Required(ErrorMessage = "Enter Your Email..")] [Display(Name = "Email")] public string Email { get; set; } [Required(ErrorMessage = "Enter Username..")] [Display(Name = "Username")] public string Username { get; set; } // 仅当允许修改密码时保留,否则可移除 [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "Confirm Password")] [Compare("Password")] public string ConfirmPass { get; set; } }
同时修改视图的@model为TA.Models.EditUserViewModel,并调整控制器中Edit方法的模型绑定逻辑。
内容的提问来源于stack exchange,提问作者Tutorial Hell Veteran
相关产品推荐
相关产品推荐

