我正在创建一个 ASP.NET Core 6.0 Web 应用程序。
我的表单验证不起作用,当我输出
ModelState
错误时,我看到以下内容:
键:电子邮件,错误:电子邮件字段为必填项。
键:密码,错误:密码字段为必填项
这些错误不会显示在我页面上的任何表单下。
在写这篇文章时,我没有更改任何代码,但出于某种原因
密钥:密码,错误:密码字段为必填项。
现在不再出现,这让我更加困惑。
我的编辑视图具有所有必要的字段,无论我尝试什么,我都无法消除错误。
为了更容易可视化,我的页面如下所示:
以下是所有相关代码:
@model Replay.ViewModels.ApplicationUserRoleViewModel
@{
ViewData["Title"] = "Edit User";
}
<h1>Edit User</h1>
<form asp-controller="Account" asp-action="Edit" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ApplicationUser.Email" class="control-label"></label>
<input asp-for="ApplicationUser.Email" class="form-control" />
<span asp-validation-for="ApplicationUser.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ApplicationUser.FullName" class="control-label"></label>
<input asp-for="ApplicationUser.FullName" class="form-control" />
<span asp-validation-for="ApplicationUser.FullName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ApplicationUser.Password" class="control-label"></label>
<input asp-for="ApplicationUser.Password" class="form-control" />
<span asp-validation-for="ApplicationUser.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ApplicationUser.Active" class="control-label"></label>
<input asp-for="ApplicationUser.Active" type="checkbox" class="form-check-input" />
<span asp-validation-for="ApplicationUser.Active" class="text-danger"></span>
</div>
<div class="form-group">
<table>
@for (int i = 0; i < Model.Roles.Count; i++)
{
<tr>
<td>
@Html.HiddenFor(m => m.Roles[i].Id)
@Html.HiddenFor(m => m.Roles[i].Name)
@Html.DisplayFor(m => m.Roles[i].Name)
</td>
<td>@Html.CheckBoxFor(m => m.Roles[i].Selected)</td>
</tr>
}
</table>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
C#代码:
using Replay.Models;
namespace Replay.ViewModels
{
public class ApplicationUserRoleViewModel
{
public ApplicationUser ApplicationUser { get; set; }
public List<RoleViewModel> Roles { get; set; }
public ApplicationUserRoleViewModel()
{
}
public ApplicationUserRoleViewModel(ApplicationUser applicationUser, List<Role> roles, List<int> userRoleIds)
{
ApplicationUser = applicationUser;
Roles = roles.Select(r => new RoleViewModel
{
Id = r.Id,
Name = r.Name,
Selected = userRoleIds.Contains(r.Id)
}).ToList();
}
}
public class RoleViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
}
using System.ComponentModel.DataAnnotations;
namespace Replay.Models;
public class ApplicationUser
{
[Key]
public int Id { get; set; }
public string Email { get; set; }
public string FullName { get; set; }
public string Password { get; set; }
public Boolean Active { get; set; }
}
using System.ComponentModel.DataAnnotations;
namespace Replay.Models
{
public class Role
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(ApplicationUserRoleViewModel viewModel)
{
if (!ModelState.IsValid)
{
foreach (var key in ModelState.Keys)
{
var state = ModelState[key];
foreach (var error in state.Errors)
{
System.Diagnostics.Debug.WriteLine($"Key: {key}, Error: {error.ErrorMessage}");
}
var roles = _dbContext.Role.ToList();
var userRoleIds = _dbContext.UserRoles
.Where(ur => ur.UserId == viewModel.ApplicationUser.Id)
.Select(ur => ur.RoleId).ToList();
viewModel.Roles = roles.Select(r => new RoleViewModel
{
Id = r.Id,
Name = r.Name,
Selected = userRoleIds.Contains(r.Id)
}).ToList();
return View(viewModel);
}
}
var user = _dbContext.ApplicationUser.Find(viewModel.ApplicationUser.Id);
if (user == null)
{
return NotFound();
}
user.Email = viewModel.ApplicationUser.Email;
user.FullName = viewModel.ApplicationUser.FullName;
user.Password = viewModel.ApplicationUser.Password;
user.Active = viewModel.ApplicationUser.Active;
var userRoles = _dbContext.UserRoles.Where(ur => ur.UserId == user.Id).ToList();
_dbContext.UserRoles.RemoveRange(userRoles);
var selectedRoleIds = viewModel.Roles
.Where(r => r.Selected)
.Select(r => r.Id).ToList();
foreach (var roleId in selectedRoleIds)
{
_dbContext.UserRoles.Add(new UserRole { UserId = user.Id, RoleId = roleId });
}
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Replay.Models
{
public class UserRole
{
[Key]
public int Id { get; set; }
[ForeignKey("ApplicationUser")]
public int UserId { get; set; }
[ForeignKey("Role")]
public int RoleId { get; set; }
}
}
我尝试过什么:
ApplicationUser.Email
和ApplicationUser.Password
),但仍然出现错误。也许很好/有趣的是,当从我的视图中删除 ApplicationUser.Email 和密码时,它特别表示现在缺少 ApplicationUser.Email、ApplicationUser.Password、电子邮件和密码。
添加 @Html.HiddenFor(),这显然甚至无法编译,因为我的 ViewModel 甚至没有电子邮件或密码。
我也尝试过添加一个?到我的 ApplicationUser 类中的电子邮件和密码。我正在使用 .NET 6.0 创建一个 Web 应用程序。我对我的验证 表单不起作用,当我输出 ModelStates 错误时它会显示 我这个:键:电子邮件,错误:电子邮件字段是必需的。钥匙: 密码,错误:密码字段为必填项。
根据您的代码,您收到的错误是由于您的模型绑定造成的。在 ASP.NET 6 中,默认情况下,模型中的不可为 null 的引用类型被视为必填字段。
由于您的
ApplicationUser
类没有任何数据注释,如 [Required]
或电子邮件和密码属性上的 Nullable(它们可能是字符串,因此不可为 null),模型绑定器在表单提交期间认为它们丢失,从而导致验证错误。因此,为了修复它,您应该定义可空性或任何您想要的注释。
为了解决这个问题,请确保您的模型具有适当的数据注释以进行验证。如果
ApplicationUser
模型字段应该是可选的,您需要相应地更新您的模型。您可以尝试如下:
public class ApplicationUser
{
[Key]
public int Id { get; set; }
[Required]
public string Email { get; set; }
public string? FullName { get; set; }
public string? Password { get; set; }
public Boolean Active { get; set; }
}
正如您所注意到的,我使用了
[Required]
和 Nullable ?
关键字。因此,如果您希望任何属性为强制属性,请将其装饰为必需或将它们标记为可为空,以便您的验证能够相应地工作。
注意:您可以参考此官方文档以获取更多示例和参考。