我是MVC5的新手,只是试图掌握ViewModels的使用。我的问题是,如果我必须在我的ViewModel的控制器中实例化我的模型类。我正在创建一个数据库来组织账单,并拥有一个映射到数据库表的Cash模型,以及一个用于查看/编辑数据的CashViewModel。
这是我的模特:
public class Cash
{
public int CashId { get; set; }
public decimal CashAmount { get; set; }
public int CashTypeId { get; set; }
public DateTime DateModified { get; set; }
public CashType CashType { get; set; }
}
这是我的ViewModel:
public class CashViewModel
{
public int CashId { get; set; }
public decimal CashAmount { get; set; }
public int CashTypeId { get; set; }
public SelectList CashTypeSelectList { get; set; }
}
这是我的控制器:
public ActionResult Create([Bind(Include = "CashAmount,CashTypeId")] CashViewModel cashVM)
{
if (ModelState.IsValid)
{
var cash = db.Cashes.Create();
cash.DateModified = DateTime.Now;
cash.CashAmount = cashVM.CashAmount;
cash.CashTypeId = cashVM.CashTypeId;
db.Cashes.Add(cash);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CashTypeId = new SelectList(db.CashTypes, "CashTypeId", "CashTypeName", cashVM.CashTypeId);
return View(cashVM);
}
我正在创建Cash模型的实例并将我的ViewModel类映射到我的模型类。它是否正确?当我开始在一个ViewModel中有几个具有多个属性的模型的项目时,这似乎会很快失控。
我读到的所有问题和文章都太模糊或太详细,我无法找到任何针对我的具体问题的内容,如果已经存在某些问题,请对不起。
答案 0 :(得分:2)
ViewModels基本上是在View和Controller之间提供一个DTO,它看起来像你在做。然而,您的模型看起来不对,因为您应该只有CashType而不是CashTypeId,因为CashType模型具有Id和Cash对其的引用。两者兼顾的问题是他们没有保持同步,实际上我甚至都不记得哪个EF选择权威。
除此之外,看起来你已经明白了。您的ViewModel有一个SelectList,其中包含要呈现的视图的值,以及一个CashTypeId,供客户端分配值。如果主要实体没有CashTypeId,则必须创建一个新的CashType对象并为其分配正确的ID(假设这是实体框架)。
最后一条建议:不要在控制器中执行这些数据库操作。查看repository pattern,甚至可以在它们之间放置一个业务层。
答案 1 :(得分:1)
我正在创建Cash模型的实例并将我的ViewModel类映射到我的模型类。它是否正确?当我开始在一个ViewModel中有几个具有多个属性的模型的项目时,这似乎会很快失控。
你在做什么没有错。但是,对于从域模型到视图模型(视图模型)的映射,您可以使用库为您执行映射。我使用AutoMapper。想象一下你有这个:
void add()
{
cout << this->qt();
}
在public class Cash {
public string Prop1 { get; set; }
}
public class CashViewModel {
public string Prop1 { get; set; }
}
启动方法中,您可以指示AutoMapper如何从您的域模型映射到您的视图模型,如下所示:
Application_Start()
然后在您的控制器中,您只需将视图模型转换为域模型:
protected void Application_Start()
{
// ReverseMap will do vice-versa mapping
// If property names are the same, then AutoMapper will take care of it
// for you.
Mapper.Initialize( x => x.CreateMap<Cash, CashViewModel>().ReverseMap() );
// Of course you will have many cases where the property names
// are different
// For that case you will need to do this
// Imagine your model has a property called Name and view model has
// FirstName
Mapper.CreateMap<CashViewModel, Cash>()
.ForMember(model => model.Name, map => map.MapFrom(vm => vm.FirstName));
}
这种方法的优点在于您的所有映射都将在一个地方。总之,here是一篇很棒的文章,涵盖了您正在寻找的大部分内容以及更多内容。