ViewModel-C#ASP.NET核心的模型状态无效

ViewModel-C#ASP.NET核心的模型状态无效,c#,asp.net-core-mvc,C#,Asp.net Core Mvc,希望这是一个基本问题,我已经为联系人创建了一个“创建”页面,该页面创建了系统中所有客户的列表。我使用ViewModel来实现这一点,这很好。但是,现在在Customers模型上,我已将CustomerName字段指定为必填字段,这导致ModelState.IsValid为false,我无法找出原因 顾客 public class Customer { public int CustomerId { get; set; } [Required]

希望这是一个基本问题,我已经为联系人创建了一个“创建”页面,该页面创建了系统中所有客户的列表。我使用ViewModel来实现这一点,这很好。但是,现在在Customers模型上,我已将CustomerName字段指定为必填字段,这导致ModelState.IsValid为false,我无法找出原因

顾客

public class Customer
    {
        public int CustomerId { get; set; }
        [Required]
        [Display(Name = "Customer Name")]
        public string? CustomerName { get; set; }
        public ICollection<Contact> Contacts { get; set; }
        public ICollection<Job> Jobs { get; set; }
    }
视图模型

    public class ContactDetailViewModel
    {
        public Contact Contact { get; set; }
        public Customer Customer { get; set; }
        public List<SelectListItem> Customers { get; set; }
    }
公共类ContactDetailViewModel
{
公共联系人{get;set;}
公共客户客户{get;set;}
公共列表客户{get;set;}
}
形式


控制器

public async Task<IActionResult> Create([Bind("ContactId,FirstName,LastName,EmailAddress,Telephone")] Contact contact, ContactDetailViewModel contactDetailViewModel)
        {
            contact.Customer = await _context.Customers.FirstOrDefaultAsync(c => c.CustomerId == contactDetailViewModel.Customer.CustomerId);
            //Has to be a better way of doing this??? Why is it faling without... 06/03/2021
            //ModelState.Remove("Customer.CustomerName");

            if (ModelState.IsValid)
            {
                _context.Add(contact);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(contact);
        }
public async Task Create([Bind(“ContactId,FirstName,LastName,EmailAddress,Telephone”)]联系人,联系人详细视图模型ContactDetailViewModel)
{
contact.Customer=wait\u context.Customers.FirstOrDefaultAsync(c=>c.CustomerId==contactDetailViewModel.Customer.CustomerId);
//必须有一个更好的方法来做到这一点???为什么没有…2021年3月6日它会失败
//ModelState.Remove(“Customer.CustomerName”);
if(ModelState.IsValid)
{
_添加(联系人);
wait_context.SaveChangesAsync();
返回重定向到操作(名称(索引));
}
返回视图(联系人);
}
如果我不包括ModelState.Remove(“Customer.CustomerName”);那就不行了。但是,我不想对CustomerName做任何事情,因为我只想更新Contact.Customer,使其成为“新的”选定客户


谢谢

你的课上有错误。将CustomerId添加到联系人:

public class Contact
    {
        public int ContactId { get; set; }
        [Required]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
        [Required]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        [Display(Name = "Email Address")]
        public string EmailAddress { get; set; }
        public string Telephone { get; set; }
        public int  CustomerId { get; set; }
        public virtual  Customer Customer { get; set; }
    }
并修复视图:

<div class="form-group">
                <label asp-for="Customer.CustomerName" class="control-label"></label>
                <select class="form-control dropdown" asp-for="Contact.CustomerId" asp-items="@Model.Customers">
                    <option></option>
                </select>
                <span asp-validation-for="Contact.CustomerId" class="text-danger"></span>
            </div>
但这是一个冗余代码。您根本不需要此代码,因为您可以在不使用此代码的情况下保存联系人

您还需要通过添加CustomerId来修复绑定:

public async Task<IActionResult> Create([Bind("ContactId, CustomerId, FirstName,LastName,EmailAddress,Telephone")] Contact contact, ContactDetailViewModel contactDetailViewModel)
public async Task Create([Bind(“ContactId,CustomerId,FirstName,LastName,EmailAddress,Telephone”)]联系人,联系人详细视图模型ContactDetailViewModel)
顺便说一句,您在模型中包含整个客户仅用于

  <label asp-for="Customer.CustomerName" class="control-label"></label>

您可以将Customer属性保留为null并使用以下代码:

  <label asp-for="Contact.CustomerId" class="control-label"> Customer </label>
客户

您的
客户。CustomerName
根本没有绑定,您绑定的是
客户。CustomerId
:)。因此,客户端验证甚至通过了。
CustomerName
的验证错误也适用于
CustomerId
。非常感谢。我还必须对创建操作上的LINQ查询进行更改,以使用Contact.CustomerId而不是Customer.ContactId,但我相信这没问题?是的。我更新了我的答案。如果答案对你有帮助,请不要忘记接受。否则,土狼会立即否决它。@DanielHill奇怪的是,这个代码对您有效,它甚至与
CustomerName
的所需值无关。当然,您需要的可能是
CustomerId
,但只要视图模型具有所需的
CustomName
,该值也应该绑定。所以不要告诉我这个
@无望的联系方式是保存的而不是客户的。因为联系人只有从下拉列表中选择的CustomerName,所以CustomerName与此完全相关。@Sergey确定吗?再次仔细查看OP问题中的类
Customer
。您是否看到
客户名称上应用的
[必需]
。此视图模型
ContactDetailViewModel
已绑定(在
Create
方法中),这意味着整个视图模型的图形已绑定,包括
ContactDetailViewModel.Customer
。因此,如果
CustomerName
未绑定,验证将失败(正如他在问题中所描述的那样)。我甚至没有看到你提到他为什么会犯那个错误。为什么?你现在能解释一下吗?
public async Task<IActionResult> Create([Bind("ContactId, CustomerId, FirstName,LastName,EmailAddress,Telephone")] Contact contact, ContactDetailViewModel contactDetailViewModel)
  <label asp-for="Customer.CustomerName" class="control-label"></label>
  <label asp-for="Contact.CustomerId" class="control-label"> Customer </label>