ASP.NET Core 6.0 表单验证错误:“fieldNameHere 字段是必需的。”即使不存在这样的字段

问题描述 投票:0回答:1

我正在创建一个 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 类中的电子邮件和密码。
    我在期待什么: 我期望模型是有效的,并且没有某种“幽灵输入”?使其无效。
c# asp.net-mvc asp.net-core model-validation
1个回答
0
投票

我正在使用 .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
?
关键字。因此,如果您希望任何属性为强制属性,请将其装饰为必需或将它们标记为可为空,以便您的验证能够相应地工作。

注意:您可以参考此官方文档以获取更多示例和参考。

© www.soinside.com 2019 - 2024. All rights reserved.