views:

710

answers:

3

In my ASP.NET MVC app, I have a fairly complex edit page which combines a number of models into one view.

I'm using the ViewModel pattern to combine all of this information and present one cohesive object to the View.

As an example, my ViewModel structure is something like this:

CompanyId
CompanyName
List<Employee> Employees
List<ContactMethod> ContactMethods

The Employee object has a number of basic properties, and a preferred contact method.

On the edit page, the user is given all of the employees of the company and they have the ability to add and remove (using javascript), as well as edit employee details. The ContactMethods list is used to populate the dropdown for each employee.

I've successfully translated my Models (read from the database) into this ViewModel and back again, so after an edit, I'm left with a ViewModel representing the current state of that company's employees.

I'm using a Repository pattern to communicate with the database, so my question is, should I call directly into the CompanyRepository, passing the ViewModel, or should I convert the ViewModel back into Model objects first before using the Repository to write them to the database?

In short, should the Repository know about my ViewModel objects?

+4  A: 

I would convert the ViewModel back into Model objects first. I like keeping the dependency between my Web layer and Repository layers as loose as possible.

I don't think your Repository should know about your ViewModel, since that's a web level concept.

manu08
If that's the case (and this is fine), I'd need to either create these Employee Models, delete all existing Employees from that Company, then add the new Employee Models... or ... Retrieve all Employee models from the database and match them up before adding, removing, and editing where appropriate. Does that sound right?
Damovisa
@Damovisa: you could do that. Instead, I'd maintain that information during the edit. In your ViewModel maintain three lists: CreatedEmployees, EditedEmployees, DeletedEmployees.
manu08
@manu80 - I see how that could work, but it might get a bit complicated. The UI would have to change quite a bit to account for these three collections - even if it's only the javascript changing.
Damovisa
@Damovisa: you have to handle the complexity somewhere. If you go your original route, I would just drop all existing employees and add the new ones. That is, unless there's a real value add from adding the complexity of your second option.
manu08
@manu01 - nope, I agree with your first suggestion - that's probably the way to go. In my (real) system, it's perfectly reasonable to clear all the child objects and recreate them.
Damovisa
+3  A: 

ViewModel is the model to the view (UI), so repository shouldn't know about the view model. Separating them will keep repository loosely coupled from the UI.

Use another layer like service layer, to encapsulate repository from the UI. This layer also does the ViewModel - Model conversation and do respository call.

public class ServiceLayer
{
   public void SaveModel(ViewModel viewmodel)
   {
      var model = viewModel.ToModel();
      repository.Save(model)
   }
}
Hery
Why make the ServiceLayer depend on the ViewModel? Instead call viewModel.ToModel in the view layer, and then pass the model down to the service.
manu08
@Hery - Yes, it sounds good, but there'd be a lot more to it than just passing a model up to Repository. Employee models may be new, changed, or removed.
Damovisa
@manu: it's just a different way to implement, depend on how you want to encapsulate your repository from the view. But I can list some of the benefit like:- Perform some business validations that aren't covered by the ToModel conversion.- Keep repository model simple and generic, while service layer do more specific tasks that are tied up to the viewmodeljust my 2 cents :)
Hery
+1  A: 

I would agree with the previous answer of converting ViewModels back into "plain" Models, but would add that this task should probably be carried out by a separate service layer. This layer would be responsible for disassembling your ViewModels and acting appropriately.

This is essentially the definition of a service: something whose job is to carry out a logical unit of work that requires multiple models and/or complex logic.

Jomdom
I think this adapting should be separate from the Controllers, but I don't think it fits in a totally separate layer either. It is a View layer concept only, and should fall into lower layers at all. You can just create Adapters or some type of helper class in the same layer as the Controllers/Views.I would save that service layer (that's between the repository and view layer) for validating the models.
manu08