C# 为什么DbContext.Entry(IEnumerable<;MedicalProduct>;).State在我的代码中生成ArguementNullException?
在我的C# 为什么DbContext.Entry(IEnumerable<;MedicalProduct>;).State在我的代码中生成ArguementNullException?,c#,asp.net-mvc,entity-framework,asp.net-mvc-4,razor,C#,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,Razor,在我的MedicalProductController中,我试图使我的Edit操作能够在一个页面上编辑多个对象。为此,我计划使用HTTPPOSTedit操作方法接收IEnumerable,而不是脚手架为我设置的MedicalProduct 当我单击save提交一些更改时,我在以下行中得到一个未处理的ArguementNullException\u db.Entry(productList).State=EntityState.ModifiedmodelItem.ID) @LabelFor(ite
MedicalProductController
中,我试图使我的Edit
操作能够在一个页面上编辑多个对象。为此,我计划使用HTTPPOST
edit操作方法接收IEnumerable
,而不是脚手架为我设置的MedicalProduct
当我单击save提交一些更改时,我在以下行中得到一个未处理的ArguementNullException
\u db.Entry(productList).State=EntityState.Modified我不明白为什么它是空的
医疗产品控制器:
公共类MedicalProductController:控制器
{
私有MvcMedicalStoreDb_db=新的MvcMedicalStoreDb();
//为了简洁起见,省略了一些代码
公共操作结果编辑(int id=0)
{
MedicalProduct product=\u db.Products.Find(id);
如果(产品==null)
{
返回HttpNotFound();
}
var productList=新列表{product};
var viewModel=GetMedicalProductViewModelList(productList);
返回视图(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
公共操作结果编辑(IEnumerable productList)
{
if(ModelState.IsValid)
{
_db.Entry(productList).State=EntityState.Modified;
_db.SaveChanges();
返回操作(“索引”);
}
//var productList=新列表{product};
var viewModel=GetMedicalProductViewModelList(productList);
返回视图(viewModel);
}
}
Edit.cshtml:
@model IEnumerable
@{
ViewBag.Title=“编辑”;
}
编辑
@使用(Html.BeginForm()){
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
医药产品
@foreach(模型中的var modelItem)
{
@Html.HiddenFor(item=>modelItem.ID)
@LabelFor(item=>modelItem.Name)
@EditorFor(item=>modelItem.Name)
@Html.ValidationMessageFor(item=>modelItem.Name)
@LabelFor(item=>modelItem.Price)
@EditorFor(item=>modelItem.Price)
@Html.ValidationMessageFor(item=>modelItem.Price)
@LabelFor(item=>modelItem.BrandName)
@Html.DropDownListFor(item=>modelItem.BrandName,modelItem.BrandSelectListItem)
@Html.ValidationMessageFor(item=>modelItem.BrandName)
}
}
@ActionLink(“返回列表”、“索引”)
@节脚本{
@Scripts.Render(“~/bundles/jqueryval”)
}
在我看来,模型绑定器无法绑定到您的收藏,这将导致它为null
。它这样做的原因是您没有为每个元素指定索引。这意味着MVC无法确定如何正确绑定它们
编辑
我已经弄明白了为什么这个答案的最后一次修订不起作用。首先,IEnumerable
没有直接索引器。相反,您可以使用Model.ElementAt(i).ID
访问ID
属性。但是,这实际上并不能解决模型绑定问题,因为出于某种原因,这不会为生成的
字段在名称
属性上生成适当的索引。(更多信息请参见下文。)
有两种方法可以解决这个问题。第一种方法是将列表
传递给视图,而不是IEnumerable
,然后访问前面显示的字段。但是,更好的方法是创建一个EditorTemplate
。这将更容易,因为它使您无需更改生成视图模型的现有方法。因此,您需要遵循以下步骤:
EditorTemplates
文件夹(例如,如果视图是Home\Index.cshtml
,则创建文件夹Home\EditorTemplates
)MedicalProductViewModel
)@model MedicalProductViewModel
@Html.HiddenFor(item => Model.ID)
<div class="editor-label">
@Html.LabelFor(item => Model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Name)
@Html.ValidationMessageFor(item => Model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Price)
@Html.ValidationMessageFor(item => Model.Price)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.BrandName)
</div>
<div class="editor-field">
@Html.DropDownListFor(item => Model.BrandName, Model.BrandSelectListItem)
@Html.ValidationMessageFor(item => Model.BrandName)
</div>
<input name="ID" type="text" value="1" />
<input name="Name" type="text" value="Name 1" />
<input name="ID" type="text" value="2" />
<input name="Name" type="text" value="Name 2" />
虽然我在开始时做了一个简短的解释,但我真的应该解释一下这到底在做什么。原始HTML将产生如下输出:
@model MedicalProductViewModel
@Html.HiddenFor(item => Model.ID)
<div class="editor-label">
@Html.LabelFor(item => Model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Name)
@Html.ValidationMessageFor(item => Model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Price)
@Html.ValidationMessageFor(item => Model.Price)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.BrandName)
</div>
<div class="editor-field">
@Html.DropDownListFor(item => Model.BrandName, Model.BrandSelectListItem)
@Html.ValidationMessageFor(item => Model.BrandName)
</div>
<input name="ID" type="text" value="1" />
<input name="Name" type="text" value="Name 1" />
<input name="ID" type="text" value="2" />
<input name="Name" type="text" value="Name 2" />
如您所见,这些字段现在有一个与之关联的索引。这为模型绑定器提供了将所有项目添加到集合中所需的所有信息。现在这已经不重要了,我们可以继续修复您的产品保存代码
Gert所说的关于您试图保存productList
的方式仍然是正确的。您需要在该集合中的每个项目上设置EntityState.Modified
标志:
if (ModelState.IsValid)
{
foreach (var product in productList)
_db.Entry(product).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
看看这是否有效。我本以为会出现
invalidoOperationException
声明productList
不是模型的一部分。因为这似乎是错误的:您应该设置单个产品的状态。当我在cshtml文件中使用该代码时,我得到一个编译错误:>无法将带[]的索引应用于“System.Collections.Generic.IEnumerable”类型的表达式@ArmorCode更新了我的答案。希望这对你现在有用。我不确定我是否完全理解。编译器如何知道将编辑器模板文件中的内容放入Html.Editorfor(m=>m)
?我的理解是,强类型的@model IEnumerable
告诉视图,对于g
<input name="[0].ID" type="text" value="1" />
<input name="[0].Name" type="text" value="Name 1" />
<input name="[1].ID" type="text" value="2" />
<input name="[1].Name" type="text" value="Name 2" />
if (ModelState.IsValid)
{
foreach (var product in productList)
_db.Entry(product).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}