重要提示:我已编辑此问题以反映Jannagy02的回答,该回答消除了下拉列表问题
我有一个关于ASP.NET MVC 4和实体框架的概念性问题。
首先,让我们来看看我的模型:
此广告最多可归待一台设备。一个设备有一个类别,制造商,状态和0..n评论。这被剥夺了。学习MVC时,我不想过于复杂。因此,我们只需关注Device
和Category
,同时忽略存储库和工作单元模式等内容。
在我设置了它之后,脚手架发挥了它的魔力,生成的视图只显示了设备的Name
属性。
我的计划是,在创建或更新设备时,用户(而不是管理员)只能从已经存在的类别中进行选择。因此,下拉列表。
为此,我创建了一个ViewModel:
public class DeviceEditViewModel
{
public Device dev { get; set; }
public int? SelectedManufactor { set; get; }
public IEnumerable<SelectListItem> Manufactors { get; set; }
public int? SelectedCategory { set; get; }
public IEnumerable<SelectListItem> CategoriesListItems { get; set; }
}
GET编辑方法如下所示:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var device = db.Devices.Find(id);
var vm = new DeviceEditViewModel
{
dev = device,
Categories = db.Categories.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name,
Selected = x == device.Category
})
};
return View(vm);
}
这是我的第一个问题:生成的下拉列表无法获取设备的实际类别。那么我该如何选择实际类别作为选定值?
其次,当我点击保存按钮时,如何将此选定的ListItem作为设备模型的类别注入,这在post方法中如何反映,如下所示:
//Edited to reflect answer
public ActionResult Edit(DeviceEditViewModel editViewModel)
{
if (ModelState.IsValid)
{
Device device = editViewModel.dev;
if (editViewModel.SelectedCategory != null)
{
Category selectedCat = db.Categories.Single(x => x.ID == editViewModel.SelectedCategory.Value);
device.Category = selectedCat;
}
db.Entry(device).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(editViewModel);
}
这是我视图的DropDownList部分:
<div class="control-group">
@Html.LabelFor(model => model.dev.Category, new { @class = "control-label" })
<div class="controls">
@Html.DropDownListFor(x => x.CategoriesListItems, Model.CategoriesListItems)
@Html.ValidationMessageFor(model => model.dev.Category, null, new { @class = "help-inline" })
</div>
</div>
剩下的问题在于POST方法。我已经写了一段时间,以便能够更好地调试它。实际问题是:
使用类别更新设备,但在db.SaveChanges()
调用后,它不会写入数据库。
答案 0 :(得分:1)
首先修改ViewModel,使其包含所选值:
public class DeviceEditViewModel
{
public Device dev { get; set; }
public IEnumerable<SelectListItem> Manufactors { get; set; }
public int? SelectedCategory { set; get; }
public IEnumerable<SelectListItem> Categories { get; set; }
public IEnumerable<SelectListItem> Status { get; set; }
}
第二
在视图中绑定SelectedCategory以便它可以发布:
@Html.DropDownListFor(m => m.SelectedCategory, m.Categories)
或使用此
@Html.DropDownListFor(m => m.SelectedCategory, new SelectList(m.Categories, "ValuePropertyName", "TextPropertyName"))
将ViewModel发布到编辑而不是设备:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeviceEditViewModel devm)
{
if (ModelState.IsValid)
{
devm.device.CategoryId = devm.SelectedCategory; // <- Main thing to do
db.Entry(devm.device).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(devm);
}
答案 1 :(得分:0)
在我让问题休息了几天之后,我找到了一个有效的解决方案。实际编辑项目及其属性并将其保存到数据库的最后一个问题,一旦我管理以缩小可能发生错误的位置,这是非常微不足道的。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeviceEditViewModel editViewModel)
{
if (ModelState.IsValid)
{
//non-working: Device device = editViewmodel.env;
Device device = db.Devices.Single(x => x.Id == editViewModel.dev.Id); /*working*/
if (editViewModel.SelectedCategory != null)
{
device.Category = db.Categories.Where(x => x.ID == editViewModel.SelectedCategory).Select(x => x).Single();
}
db.Entry(device).State = EntityState.Modified;
db.Devices.AddOrUpdate(device);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(editViewModel);
}
我没有使用所使用的Viewmodel,而是通过比较ID并在此实体上调用AddOrUpdate()来从数据库中获取要编辑的设备。
现在就像魅力一样。然而,我会给解决方案点击我的下拉列表助手答案。否则不公平。