单击保存以提交我的表单时,我的 HTTPPost 编辑操作收到一个空值IEnumerable<MedicalProduct> productList
。我不确定要为我的编辑操作使用什么参数来防止空值。我会尝试用一些断点来确定原因,但在将参数分配为 null 之前找不到该点。
边注:
我正在调整我的代码以使用这个新的模型/视图模型层次结构。我的控制器尚未使用这些新模型进行完全测试,但我开始测试编辑操作,并在尝试IEnumerable<MedicalProduct> productList
在我的编辑发布操作中使用参数时收到空引用异常。
另一个旁注:
我在 ViewModel 中使用了一个子 ViewModel 类MedicalProductViewModelLineItem
(还没有找到更好的名称),MedicalProductViewModel
因为我需要一种方法来通过一次数据库调用从数据库中检索所有品牌名称,然后将它们一一分配给MedicalProductViewModelLineItem
.
编辑:代码更新 2013 年 10 月 22 日下午 5:14 CST。FormCollection.Keys
HttpPostEdit
操作方法生成的值现在,像“Products[0].Name”或“Products[0].ID”这样的值是在FormCollection.Keys
参数中生成的,而不是“p.Name”或“Name”。 不过,productList
参数依旧null
。
模型类
医疗产品视图模型
public class MedicalProductViewModel
{
public List<MedicalProductViewModelLineItem> Products { get; private set; }
//public SelectListItem BrandSelectListItem { get; private set; }
public void BuildViewModel(IEnumerable<MedicalProductViewModelLineItem> productsList, IEnumerable<Brand> brandList)
{
BuildProducts(productsList, brandList);
}
public void BuildViewModel(IEnumerable<MedicalProduct> productsList, IEnumerable<Brand> brandList)
{
BuildProducts(productsList, brandList);
}
private IEnumerable<SelectListItem> BuildSelectListItems(IEnumerable<Brand> brandList)
{
return brandList.Select(b => new SelectListItem()
{
Text = b.Name,
Value = b.ID.ToString()
});
}
private void BuildProducts(IEnumerable<MedicalProductViewModelLineItem> productList, IEnumerable<Brand> brandList)
{
var medicalProducts = productList.Select(p => new MedicalProduct()
{
BrandID = p.BrandID,
ID = p.ID,
Name = p.Name,
Price = p.Price
});
BuildProducts(medicalProducts, brandList);
}
private void BuildProducts(IEnumerable<MedicalProduct> productsList, IEnumerable<Brand> brandList)
{
Products = productsList.Select(p => new MedicalProductViewModelLineItem()
{
BrandID = p.BrandID,
BrandName = brandList.Single(b => b.ID == p.BrandID).Name,
BrandSelectListItem = BuildSelectListItems(brandList),
ID = p.ID,
Name = p.Name,
Price = p.Price
}).ToList();
}
}
MedicalProductViewModelLineItem
// Sub-ViewModel of MedicalProductViewModel
// It gets displayed as one row on a view.
public class MedicalProductViewModelLineItem
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
// is a foreign key
public int BrandID { get; set; }
public string BrandName { get; set; }
}
医疗产品
// DOMAIN MODEL
public class MedicalProduct
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
// is a foreign key
public int BrandID { get; set; }
}
控制器
医疗产品控制器
public class MedicalProductController : Controller
{
private MvcMedicalStoreDb _db = new MvcMedicalStoreDb()
//
// GET: /MedicalSupply/Edit/5
public ActionResult Edit(int id = 0)
{
MedicalProduct product = _db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
var productList = new List<MedicalProduct> { product };
var viewModel = GetMedicalProductViewModel(productList);
return View(viewModel);
}
// ==========================================
// NULL REFERENCE EXCEPTION OCCURS IN THIS ACTION
// ==========================================
// POST: /MedicalSupply/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(IEnumerable<MedicalProductViewModelLineItem> productList, FormCollection values)
{
if (ModelState.IsValid)
{
foreach (var product in productList)
_db.Entry(product).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
var productViewModelList = GetMedicalProductViewModel(productList);
return View(productViewModelList);
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
}
意见
编辑.cshtml
@model MvcMedicalStore.Models.MedicalProductViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>MedicalProduct</legend>
@for (int i = 0; i < Model.Products.Count(); i++)
{
@Html.EditorFor(m => m.Products[i])
}
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
EditorTemplates\MedicalProductViewModelLineItem.cshtml
@model MvcMedicalStore.Models.MedicalProductViewModelLineItem
@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.BrandID)
</div>
<div class="editor-field">
@Html.DropDownListFor(item => Model.BrandID, Model.BrandSelectListItem)
@Html.ValidationMessageFor(item => Model.BrandID)
</div>
编辑:(图片已过时)
该方法的两个图像,以及 MedicalProductViewModel.cshtml 中使用的foreach
方法,以及参数for
的结果键值FormsCollection
values