ViewModel-C#ASP.NET核心的模型状态无效
希望这是一个基本问题,我已经为联系人创建了一个“创建”页面,该页面创建了系统中所有客户的列表。我使用ViewModel来实现这一点,这很好。但是,现在在Customers模型上,我已将CustomerName字段指定为必填字段,这导致ModelState.IsValid为false,我无法找出原因 顾客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]
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>