如何防止Asp.NET Razor Pages提交表单时清空字段?
注册失败时表单字段被清空的解决办法
我有一个注册页面,注册成功会跳转到Index页面;但注册失败时,页面会显示错误信息,可所有表单字段都会被清空,怎么避免这个问题?我试过用JS的preventDefault(),但它会阻止表单提交,根本解决不了问题。另外我的OnGet方法是空的。
前端表单代码
<form method="post" asp-page-handler="Register" id="myForm"> <div asp-validation-summary="All" class="text-danger"> </div> <div class="edit-profile__body"> <div class="form-group mb-20"> <label for="name">User name</label> <input type="text" class="form-control" name="UserName" id="name" placeholder="user name"> </div> <div class="form-group mb-20"> <label for="username">showing name</label> <input type="text" class="form-control" id="username" name="ShowName" placeholder="showing name"> </div> <div class="form-group mb-20"> <label for="email">Email</label> <input type="text" class="form-control" name="Email" id="email" placeholder="name@example.com"> </div> <div class="form-group mb-15"> <label for="password-field">password</label> <span asp-validation="password"></span> <div class="position-relative"> <input id="password-field" type="password" class="form-control" name="password" placeholder="password"> <div class="uil uil-eye-slash text-lighten fs-15 field-icon toggle-password2"></div> </div> </div> <div class="admin-condition"> <div class="checkbox-theme-default custom-checkbox"> <input class="checkbox" type="checkbox" name="ConfirmRules" id="admin-1" value="true"> <label for="admin-1"> <span class="checkbox-text"> I accept <a href="#" class="color-primary">Rules</a> </span> </label> </div> </div> <div class="admin__button-group button-group d-flex pt-1 justify-content-md-start justify-content-center"> <button type="submit" id="formSubmit" class="btn btn-primary btn-default w-100 btn-squared text-capitalize lh-normal px-50 signIn-createBtn "> Create Account </button> </div> </div> </form>
后端处理代码
public async Task<IActionResult> OnPostRegister(SignUpVM signUpVM, CancellationToken cancellationToken) { UserManagerResponse result; if (ModelState.IsValid && signUpVM.ConfirmRules) { var model = new UserDTO() { UserName = signUpVM.UserName, ShowName = signUpVM.ShowName, Email = signUpVM.Email, Password = signUpVM.Password, }; result = await _userAppServices.Register(model, cancellationToken); if (result.IsSuccess) { return LocalRedirect("Index"); } else { ModelState.AddModelError(string.Empty, result.Message); return default; } } else { return default; } }
解决步骤
1. 修改后端方法,返回携带ViewModel的Page
原来的return default;会返回空页面结果,不会携带用户提交的表单数据。改成return Page();后,Razor Pages会自动把当前的signUpVM和ModelState传递回页面,用来填充表单字段。
修改后的后端代码:
public async Task<IActionResult> OnPostRegister(SignUpVM signUpVM, CancellationToken cancellationToken) { UserManagerResponse result; if (ModelState.IsValid && signUpVM.ConfirmRules) { var model = new UserDTO() { UserName = signUpVM.UserName, ShowName = signUpVM.ShowName, Email = signUpVM.Email, Password = signUpVM.Password, }; result = await _userAppServices.Register(model, cancellationToken); if (result.IsSuccess) { return LocalRedirect("Index"); } else { ModelState.AddModelError(string.Empty, result.Message); // 返回Page(),保留表单数据 return Page(); } } else { // 验证失败时同样返回Page() return Page(); } }
2. 给前端表单添加asp-for绑定
把原来的name属性替换成asp-for,让Razor自动绑定ViewModel的属性,页面加载时会从ModelState中读取值填充输入框。修改后的关键字段示例:
<!-- UserName字段 --> <input type="text" class="form-control" asp-for="UserName" id="name" placeholder="user name"> <!-- ShowName字段 --> <input type="text" class="form-control" asp-for="ShowName" id="username" placeholder="showing name"> <!-- Email字段 --> <input type="text" class="form-control" asp-for="Email" id="email" placeholder="name@example.com"> <!-- Password字段 --> <input id="password-field" type="password" class="form-control" asp-for="Password" placeholder="password"> <!-- ConfirmRules复选框 --> <input class="checkbox" type="checkbox" asp-for="ConfirmRules" id="admin-1">
asp-for会自动生成正确的name属性,同时完成数据绑定。
3. 密码字段的特殊处理(可选)
密码属于敏感信息,ModelState默认不会保留它的值。如果需要让用户不用重新输入密码(不推荐,存在安全风险),可以在注册失败的分支里手动把密码值添加到ModelState:
ModelState.SetModelValue(nameof(SignUpVM.Password), new ValueProviderResult(signUpVM.Password, System.Globalization.CultureInfo.InvariantCulture));
更安全的做法是让用户重新输入密码,只保留其他字段的值。
4. 完善OnGet方法(可选)
虽然空的OnGet方法也能工作,但显式返回Page()会更清晰,确保页面初始化时能正确绑定ViewModel:
public IActionResult OnGet() { return Page(); }
内容的提问来源于stack exchange,提问作者Alireza
相关产品推荐
相关产品推荐

