我正在看这个ASP.NET MVC course。我有一个customer
model
,其中包含以下属性。
public class Customer {
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[Display(Name = "Date of Birth")]
public DateTime? DateOfBirth { get; set; }
public bool IsSubscribedToNewsLetter { get; set; }
public MembershipType MembershipType { get; set; }
[Display(Name="Membership Type")]
public byte? MembershipTypeId { get; set; }
}
请注意,Id没有Required
数据注释。但是在我的数据库中,Id是主键,而该列的标识是真的。
有ViewModel
个Customer
和MembershipType
模型。
public class CustomerFormViewModel {
public IEnumerable<MembershipType> MembershipTypes { get; set; }
public Customer Customer { get; set; }
}
我有一个使用new Customer
,Name
,DateOfBirth
和MembershipType
字段创建IsSubscribedToNewsLetter
的视图。需要CustomerFormViewModel
。
@using Vidly.Models
@model Vidly.ViewModel.CustomerFormViewModel
@{
ViewBag.Title = "New";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>@ViewBag.Message</h2>
@using (Html.BeginForm("Save", "Customer")) {
<div class="form-group">
@Html.LabelFor(m => m.Customer.Name,new{@class="control-label"})
@Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(m=>m.Customer.Name)
</div>
<div class="form-group">
@Html.LabelFor(m => m.Customer.DateOfBirth, new { @class = "control-label"})
@Html.TextBoxFor(m => m.Customer.DateOfBirth,"{0:d MMM yyyy}", new { @class = "form-control" })
</div>
<div class="form-group">
@Html.LabelFor(m => m.Customer.MembershipTypeId, new { @class = "control-label"})
@Html.DropDownListFor(m => m.Customer.MembershipTypeId,new SelectList(Model.MembershipTypes,"Id","Name"), "Select Membership Type", new { @class = "form-control" })
</div>
<div class="checkbox">
<label>
@Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsLetter) Subscribed To Newsletter?
</label>
</div>
@Html.HiddenFor(m=>m.Customer.Id)
<button type="submit" class="btn btn-primary">Save</button>
}
这是我的Save
控制器:
public ActionResult Save(Customer customer) {
if (!ModelState.IsValid) {
var viewModel = new CustomerFormViewModel {
Customer = customer,
MembershipTypes = _context.MembershipTypes.ToList()
};
return View("CustomerForm", viewModel);
}
if (customer.Id == 0 || customer.Id==null) {
_context.Customers.Add(customer);
}
else {
var CustomerInDb = _context.Customers.Single(c => c.Id == customer.Id);
CustomerInDb.Name = customer.Name;
CustomerInDb.DateOfBirth = customer.DateOfBirth;
CustomerInDb.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;
CustomerInDb.MembershipTypeId = customer.MembershipTypeId;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customer");
}
当我填写CustomerForm
视图并单击提交按钮时,ModelState.Isvalid()
方法始终为false;导致if statement
方法的第一个Save
为true。所以我不能存储任何新客户。
我尝试debug
将breakpoint
放在if (!ModelState.IsValid)
上,然后看到Id
字段正在创建错误(说“需要Id字段”) 。为什么说Id
不是必需的? ModelState.IsValid
方法是否在数据库级别检查模型?我不这么认为。
如果我像这样更改Customer
模型的Id
属性:public int? Id { get; set; }
并更改if语句,if ((!ModelState.IsValid) && (customer.Id==null) )
应用程序正常工作。
这个Id
问题还有其他解决办法吗?
答案 0 :(得分:1)
我看了同样的课程,我猜你的作者自从看了之后就更新了,因为他展示了这个确切的问题类型。问题是当将View Model返回到New Action上的View时,Customer属性未初始化,因此Id为null,因此在尝试保存时ModelState失败
只需更改如下,以便在设置viewModel时初始化Customer,然后Id为0:
public ActionResult New()
{
var memberShipTypes = _context.MembershipTypes.ToList();
var viewModel = new CustomerViewModel
{
Customer = new Customer(),
MembershipTypes = memberShipTypes
};
return View("CustomerForm", viewModel);
}
答案 1 :(得分:1)
对此花了很长时间,并创建了一种解决方法,但是看来Mosh在稍后的部分中将其设置为“电影格式”。
https://codewithmosh.com/courses/222293/lectures/3684111
简短的答案是将@Html.Hidden("Movie.Id", (Model.Movie != null) ? Model.Movie.Id : 0)
添加到MovieForm.cshtml。
然后,他描述了一种避免将“ Movie.Id”硬编码到视图中的方法(请参见https://github.com/mosh-hamedani/vidly-mvc-5/commit/e5b994581931a079ad87418ddcf9338e808bd821#diff-e94a8dc96403203b00e58238bb80101c)
答案 2 :(得分:0)
问题可能是Id
字段标记为int
而非int?
。将变量设置为int
模型会自动假定该属性的值将被标记为nullable
。
尝试将Id
属性标记为int?
并查看结果是否符合您的预期。
答案 3 :(得分:0)
这只是草稿,因为我现在无法访问VS.无论如何,修改你的保存操作,如下所示:
public ActionResult Save(CustomerFormViewModel customerVM) {
if (!ModelState.IsValid) {
return View(customerVM);
}
if (customer.Id == 0) {
_context.Customers.Add(customerVM.Customer);
}
else {
var CustomerInDb = _context.Customers.Find(customerVM.Customer.Id);
CustomerInDb.Name = customer.Name;
CustomerInDb.DateOfBirth = customer.DateOfBirth;
CustomerInDb.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;
CustomerInDb.MembershipTypeId = customer.MembershipTypeId;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customer");
}
哦,您可以从视图中删除以下内容,因为这是用于创建页面:
@Html.HiddenFor(m=>m.Customer.Id)
答案 4 :(得分:0)
他们在模型类中将Id更改为CustomerId。 我认为只是&#39; Id&#39;可以被视为该模型类的主键。
答案 5 :(得分:0)
我们正在做相同的课程,我遇到了完全相同的问题大声笑。 在我看来,我找到了一个非常好的解决方法。
只需在CustomerFormView
中添加这些代码行即可。
代替
@Html.HiddenFor(m=>m.Customer.Id)
添加:
{
if (Model.Customer == null)
{
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Customer_Id" name="Customer.Id" type="hidden" value="0" />
}
else
{
@Html.HiddenFor(m => m.Customer.Id)
}
}
由于某种原因,我看到当我尝试添加新客户时,id的值是空字符串而不是零。 因此,如果Customer对象为null,我会手动将其更改为零 (添加新客户时总会如此。) 它对我来说很好。
如果您认为此解决方案存在问题,请与我们联系。
BTW关于你的问题:&#34; Id字段正在创建错误(说&#34; Id字段是必需的&#34;)。为什么说它不是必需的时候是必需的?&#34;
Int数据类型是不可为空的,因此它是隐式需要的......作为MembershipId(没有[Required]
注释的字节数据类型。)
答案 6 :(得分:0)
我也正在学习这门课程。我有同样的问题。在customerviewform中添加此行
if (Model.Customers !=null)
{
@Html.HiddenFor(m => m.Customers.Id)
}
为什么我要添加,因为虽然隐藏它用于编辑目的,如果你删除它也将是问题。那么添加这一行我们将工作并在客户模型中添加public int? Membershiptype。如果你在下拉列表中遇到错误,那么在添加新客户的同时,在验证区域返回之前添加此行
customer.MembershipTypes = _Context.MembershipTypeTableset.ToList(); add this line before View("CustomerForm", viewModel)
答案 7 :(得分:0)
此示例摘自Mosh Hamedani的MVC 5课程。他在第55章中解释了客户ID问题。可以通过在创建CustomerFormViewModel时在New方法中传递新的customer()对象来解决此问题。
答案 8 :(得分:-1)
在看到this问题之后,我解决了我的问题。我刚刚在Id
操作开始时在ModelState
中停用了Save
个错误。
public ActionResult Save(Customer customer) {
ModelState["customer.Id"].Errors.Clear();
if ((!ModelState.IsValid) ) {
var viewModel = new CustomerFormViewModel {
Customer = customer,
MembershipTypes = _context.MembershipTypes.ToList()
};
return View("CustomerForm", viewModel);
}
if (customer.Id == 0) {
_context.Customers.Add(customer);
}
else {
var CustomerInDb = _context.Customers.Single(c => c.Id == customer.Id);
CustomerInDb.Name = customer.Name;
CustomerInDb.DateOfBirth = customer.DateOfBirth;
CustomerInDb.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;
CustomerInDb.MembershipTypeId = customer.MembershipTypeId;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customer");
}
现在我的应用程序工作正常。