我是否需要在MVC5的ViewModel中实例化我的Model类?

时间:2017-02-11 19:42:55

标签: c# asp.net-mvc-5 viewmodel

我是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中有几个具有多个属性的模型的项目时,这似乎会很快失控。

我读到的所有问题和文章都太模糊或太详细,我无法找到任何针对我的具体问题的内容,如果已经存在某些问题,请对不起。

2 个答案:

答案 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是一篇很棒的文章,涵盖了您正在寻找的大部分内容以及更多内容。