我第一次尝试使用ViewModels使用AutoMapper。我有两个模型:
public class Item
{
public int ItemId { get; set; }
public bool Active { get; set; }
public string ItemCode { get; set; }
public string Name { get; set; }
public List<ItemOption> ItemOptions { get; set; }
//...
}
public class ItemOption
{
public int ItemOptionId { get; set; }
public string Name { get; set; }
public string Barcode { get; set; }
//...
}
我已经变成了两个ViewModel:
public class ItemDetailViewModel
{
public int ItemDetailViewModelId { get; set; }
public int ItemId { get; set; }
public bool Active { get; set; }
public string ItemCode { get; set; }
public string Name { get; set; }
public List<ItemDetailItemOptionViewModel> ItemOptions { get; set; }
}
public class ItemDetailItemOptionViewModel
{
public int ItemDetailItemOptionViewModelId { get; set; }
public int ItemOptionId { get; set; }
public string Name { get; set; }
public string Barcode { get; set; }
}
然后我在应用程序启动时设置了以下内容:
Mapper.CreateMap<Item, ItemDetailViewModel>();
Mapper.CreateMap<ItemOption, ItemDetailItemOptionViewModel>();
最后我搭建了我的ItemDetailViewModel:
然后我构建了我的项目并通过/ Item / Create
添加了一个新项目我在数据库中看到期望看到我在Item表中有一个条目,但我有ItemDetailViewModel和ItemDetailItemOptionViewModel表,我没想到,数据是ItemDetailViewModel。
我认为我的脚手架做错了什么?如何在不将其作为主要业务模型的一部分的情况下构建ViewModel?
更多详情
如果无法使用ViewModel搭建控制器,那么如何在控制器中引用ViewModel并将更改保存回数据库?
例如,一旦我从db上下文中删除ItemDetailViewModel,会有什么改变?
//
// POST: /Item/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ItemDetailViewModel itemdetailviewmodel)
{
if (ModelState.IsValid)
{
db.ItemDetailViewModels.Add(itemdetailviewmodel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(itemdetailviewmodel);
}
更多详情[2]
所以我更正确的是我的索引/详细信息应该如此工作还是有更好的方法呢?
//
// GET: /Item/
public ActionResult Index()
{
var items = db.Items.ToList();
var itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(items);
return View(itemdetailviewmodel);
}
//
// GET: /Item/Details/5
public ActionResult Details(int id = 0)
{
ItemDetailViewModel itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(db.Items.Find(id));
if (itemdetailviewmodel == null)
{
return HttpNotFound();
}
return View(itemdetailviewmodel);
}
答案 0 :(得分:1)
脚手架并不那么聪明。标准控制器脚手架模板正在使用控制器模型创建DbContext,并假设您正在使用数据库模型,而不是视图模型,并且它不使用自动映射。所以你需要不使用脚手架,或者在使用脚手架之前检查它是做什么的。
使用脚手架的方式没有任何问题,只是不应该做你期望的事情。
更新这是您在没有脚手架的情况下执行此操作的方法
// Without Automapper
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ItemDetailViewModel model)
{
if (ModelState.IsValid)
{
var item = new Item()
{
Active = model.Active,
ItemCode = model.ItemCode,
Name = model.Name,
ItemOptions = // code to convert from List<ItemDetailItemOptionViewModel> to List<ItemOption>
}
db.Items.Add(item);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
// with Automapper - not recommended by author of Automapper
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ItemDetailViewModel model)
{
if (ModelState.IsValid)
{
var item = Automapper.Mapper.Map<Item>(model);
db.Items.Add(item);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
您需要修改DbContext以使IDbSet<Item> Items
代替IDbSet<ItemDetailViewModels> ItemDetailViewModels
。
创建Automapper是为了从域模型映射到视图模型而不是其他方式。我已经做了一段时间,但这很麻烦,并导致细微的错误和其他维护问题。甚至吉米·博加德本人says you should not map from view models to domain models。