Who populates ViewModel in ASP MVC 5

Whose responsibility is to populate the values ​​in the ASP MVC 5 architecture (C #, EF), for example. if we have PurchaseRecordsViewModel , PurchaseRecords Domain Model , PurchaseController

  • Is the code to fill in the data (time, cost, etc.), go to it in the viewmodel, right in your own viewmodel model go to the PurchaseRecordsViewModel ?

  • Or, is the code in the Action method for the PurchaseController

+7
c # asp.net-mvc entity-framework viewmodel
source share
4 answers

Turning around on Tommy's answer, here is some code to agree with his description.

 //Controller public ActionResult Index() { List<OrderViewModel>() model = new List<OrderViewModel>(); model = new ServiceClass().GetOrders(); return View(model); } //here is your Service Class, this layer transfers the Domain Model into your ViewModel public List<OrderViewModel> GetOrders() { List<OrderDomain> model = new List<OrderDomain>(); model = new DataAccess().GetOrders(); List<OrderViewModel> viewModel = new List<OrderViewModel>(); foreach (var order in model) { OrderViewModel vm = new OrderViewModel(); vm.OrderId = order.OrderId; vm.OrderName = order.OrderName; viewModel.Add(vm); } return viewModel; } //some DataAccess class, this class is used for database access Public List<OrderDomain> GetOrders() { List<OrderDomain> model = new List<OrderDomain>(); using (var context = new MyEntities()) { model = (from x in context.Order select new OrderDomain { OrderId = x.OrderId, OrderName = x.OrderName }).ToList(); } return model; } 
+6
source share

Browse models are usually just dumb collections of properties. Filling out the presentation model usually lies within your level of service or, if you do not have one, your method of action.

Think of roles this way.

  • A domain model is a direct mapping to a database table.
  • A view model is a set of properties required to display a view.
  • The service level receives / uses one or more domain models and populates the presentation model.
  • The service level can also display a presentation model and create / update one or more domain models.
  • The controller's action method is the glue between them. It calls the service level to obtain (GET) the view model and passes it to the view. These action methods also take the (POST) view model and pass it to the service level to do whatever needs to be done with it.

Another commonly asked question is why can't I use domain models for presentation? You can, but usually you come across things like, for example, data from more than one domain model that does not require all the properties that are in the domain model, and finally, you now have to worry about updated properties in the domain model, which you did not intend.

+11
source share

Ideally, a PurchaseRecordViewModel should populate itself with a PurchaseRecordsDomainModel . It should contain a simple mapping of properties and possibly some formatting of the output that you intend to use in your view.

PurchaseRecordsViewModel

 public class PurchaseRecordsViewModel { public IEnumerable<PurchaseRecordViewModel> PurchaseRecords {get;set;} } 

PurchaseRecordViewModel

  public class PurchaseRecordViewModel { public DateTime Date {get;set;} public decimal Cost {get;set;} // .... some other properties public PurchaseRecordsViewModel(PurchaseRecordsDomainModel domainModel) { Date = domainModel.Date; Cost = domainModel.Cost; // .... some other property mappings } } 

What your action method on the PurchaseController should do is organize the process of getting the PurchaseRecordsDomainModel , creating the PurchaseRecordsViewModel from the PurchaseRecordsDomainModel and passing it to the View . action method itself should not contain any code related to connecting and retrieving data from the database (in your case, requesting the EF context) or any business logic. You should try to have loosely coupled modules while talking to each other through abstractions , so you make sure your application is maintainable , extensible and testable .

In addition, try to make a clear separation between the different levels of your system. For example, it's nice to have EF entities as Domain Model Entites . You do not want your business logic layer depend on a data access layer , think about it so that if at some point in the future you move away from EF and use some other ORM or even other technologies to store and request data. You do not want to change the business logic layer just because you are changing your data access layer . So go from words to code in your case.

Given that you already have your View and view model , I would create the PurchaseRecordsService class in the domain layer (note that depending on your case, you may not use Repositories , but some other methods, this example mainly illustrates my point of view )

 public class PurchaseRecordsService { private readonly IPurchaseRecordsRepository _purchaseRecordsRepository; public PurchaseRecordsService(IPurchaseRecordsRepository purchaseRecordsRepository) { if(purchaseRecordsRepository == null) { throw new ArgumentNullException("purchaseRecordsRepository"); } _purchaseRecordsRepository = purchaseRecordsRepository; } public IEnumerable<PurchaseRecordsDomainModel> GetPurchaseRecords() { // trivial case, real code can be more complex return _purchaseRecordsRepository.GetPurchaseRecords(); } } 

Then in the domain layer you can define IPurchaseRecordsRepository

 public interface IPurchaseRecordsRepository { IEnumerable<PurchaseRecordsDomainModel > GetPurchaseRecords(); } 

The idea is that our PurchaseRecordsService needs a way to communicate with the databases, so anyone who uses it must provide an IPurchaseRecordsRepository implementation. The next step is to go to our data access layer and create an implementation class IPurchaseRecordsRepository .

 public class EfPurchaseRecordsRepository: IPurchaseRecordsRepository { private readonly EfObjectContext _objectContext; public EfPurchaseRecordsRepository(string connectionString) { _objectContext = new EfObjectContext(connectionString); } public IEnumerable<PurchaseRecordsDomainModel > GetPurchaseRecords() { var purchaseRecords = (from p in _objectContext.PurchaseRecords .... select p).AsEnumerable(); return purchaseRecords .Select(p => p.ConvertToDomainPurchaseRecord()); } } 

And the last fragment - we need to define our action in the PurchaseController

 public class PurchaseController: Controller { private readonly IPurchaseRecordsRepository _repository; public PurchaseController(IPurchaseRecordsRepository repository) { if(repository == null) { throw new ArgumentNullException("repository"); } _repository = repository; } public ActionResult Index() { var purchaseRecordsService = new PurchaseRecordsService(_repository); var purchaseRecordsViewModel = new PurchaseRecordsViewModel(); var purchaseRecords = purchaseRecordsService.GetPurchaseRecords(); foreach(var purchaseRecord in purchaseRecords) { var purchaseRecordViewModel = new PurchaseRecordViewModel(purchaseRecord); purchaseRecordsViewModel.PurchaseRecords.Add(purchaseRecordViewModel); } return View(purchaseRecordsViewModel); } } 

Recall that we have loosely coupled code, our Presentation and Data Access Layers do not know about each other, and they depend only on the Domain level. If you need, you can replace the MVC front end with WPF , for example, move from EF to another technology, your code can be checked.

+6
source share

Ideally, your view model should not know about your domain model, so I would say that you added the logic of your population to your controller, maybe equipped with some sort of matching / population property.

But remember, when it comes to questions about where to put a certain logic, personal preferences go a long way.

+3
source share

All Articles