Reputation: 37
I'm new to MVC5 and just trying to grasp the use of ViewModels. My questions is if I have to instantiate my model class in my the controller of my ViewModel. I'm making a database to organize bills, and have a Cash model that maps to a database table, and a CashViewModel to view/edit the data.
Here is my model:
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; }
}
Here is my ViewModel:
public class CashViewModel
{
public int CashId { get; set; }
public decimal CashAmount { get; set; }
public int CashTypeId { get; set; }
public SelectList CashTypeSelectList { get; set; }
}
Here is my controller:
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);
}
I'm creating an instance of the Cash model and mapping my ViewModel class to my model class. Is this correct? When I start doing projects where there are several Models with several attributes in one ViewModel, this seems like it will get out of hand quickly.
All the questions and articles I read are either too vague or too detailed and I can't find anything to my specific question, sorry if there is something already out there.
Upvotes: 2
Views: 1512
Reputation: 263
ViewModels are basically to provide a DTO between the View and Controller, which it looks like your doing. Your model however looks wrong as you should only have CashType, not CashTypeId as the CashType model has that Id and Cash has a reference to it. The problem with having both is they do not stay in sync and I actually don't even remember which one EF picks as authoritative.
Other than that it looks like you've figured it out. Your ViewModel has a SelectList with the values for your view to render and a CashTypeId for your client to assign the value to. Without CashTypeId on your primary entity you would have to create a new CashType object and assign the proper id to it (assuming this is Entity Framework).
One last piece of advice: don't do these DB operations in your controller. Check out the repository pattern, and maybe even put a business layer between them.
Upvotes: 2
Reputation: 27009
I'm creating an instance of the Cash model and mapping my ViewModel class to my model class. Is this correct? When I start doing projects where there are several Models with several attributes in one ViewModel, this seems like it will get out of hand quickly.
There is nothing wrong with what you are doing. However, for mapping from your domain model to your model for the view (view model), you can use a library to do the mapping for you. I use AutoMapper. Imagine you have this:
public class Cash {
public string Prop1 { get; set; }
}
public class CashViewModel {
public string Prop1 { get; set; }
}
In your Application_Start()
start method, you can instruct AutoMapper how to map from your domain model to your model for the view like this:
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));
}
Then in your controller you just do this to convert from a view model to a domain model:
var model = Mapper.Map<Cash>( cashViewModel );
The beauty of this approach is that all your mapping will be in one place. In conclusion, here is a great article that covers most of what you are looking for and more.
Upvotes: 1