In researching MVC 3 archetectures, one thing I've seen consistently is the concept of breaking the models out into their own project and calling it ViewModels.
As I'm coding, I'm having a hard time realizing what the benefit of this is. Could someone explain what the advantages of this are?
I'm not sure where you go thid idea that View models should be in their own project. That's typically not how it's done.
Often the business model is in a seperate project, as is the data model, but the view models are typically in the web project where they belong, since they're a part of the presentation layer.
Because one major thing about MVC is seperation of concern. You should create a ViewModel that has only the data your View needs, no logic.
You can, but you don't need, a seperate project (for example: a Data Access Layer)
A ViewModel is just a simple POCO class (Plain Old CLR Object, a class that only has properties, no logic)
More Information
Wikipedia - Model–view–controller
ASP.NET MVC
ASP.NET MVC View Model Patterns
ASP.NET MVC Tip #50 – Create View Models
What is POCO?
Use ViewModels to manage data & organize code in ASP.NET MVC applications
ViewModels are used to tailor a Model for the use of a particular View. When you want to pass specific information to the View, or retrieve particular information, then you would construct a ViewModel.
An example of a ViewModel would be:
public class PersonViewModel
{
public Person NewPerson { get ; set ; }
public Address NewAddress { get ; set ; }
public SelectList Suffixes { get ; set ; }
}
If you had a view that created a new person, you could pass it this ViewModel class that is designed soley for the purpose of a new person View.
View models are a part of the UI layer so they should generally stay in the same project.
Related
I have a viewmodel that can be use in the Controllers, View, and Core. The Core is a seperate project while the Controllers and View is in the Web Project. Where is the best location to put the ViewModel, is it in the Web project or in the Core, or do I need to created a seperate project for the View Model only?
I have a viewmodel that can be use in the Controllers, View, and Core.
No. You are not using it in the Core. Google "Separation of Concerns". The responsibility of the view model is to represent the Model (the Core project) in the view. It should not be used for anything else. I've written about view models here: http://blog.gauffin.org/2011/07/three-reasons-to-why-you-should-use-view-models/
It's the controllers responsibility to take everything from the Model (core
project) and create an appropriate view model.
Putting the view model somewhere so it can be used in the Core gives it more than one reason to change which will break the Single Responsibility Principle (one of the five SOLID principles). What it means is that several parts of your application will be affected by every change that you make and it will likely lead to small workarounds or quick fixes which will give you a maintenance nightmare in a year of so.
Update
Example using AutoMapper:
public class FlairController
{
public FlairController(IYourServiceOrRepository repos)
{
}
public ActionResult Details(int id)
{
SomeCoreObject entity = _repos.Get(id);
FlairViewModel model = new FlairViewModel();
Mapper.Map(entity, model);
return View(model);
}
}
Your example code (in the comment) is how the method would look like without a mapping framework.
Since ViewModels are specific to the Views, I would usually create a ViewModel folder under my UI project and keep it there.
I will create a seperate Service Layer ( another project) for bridging data between my ViewModels and Entity Models. My Controller Action methods call the service layer with the ViewModel object.
The view model is typically a wrapper around the model that has the UI formatted data. You should probably keep your model class in the Core project and the view model class in your web project.
The constructor for your View Model class can take an instance of your model class (and any other objects you need to populate your view) and generate the proper view data. For example, if you model has a DateTime object, then your view model could have a corresponding String property that contains the DateTime in the format you want to show.
I have to gradually replace an ASP.NET Web Forms application with an ASP.NET MVC3 layered application. Let's take into consideration just the Repository layer.
In my new MVC application I have one project for Data (name MVC.Data) and one for Web.
In the MVC.Data I have an edmx file with the EF classes, which models just the DB table (no views), and a Respository class myRepository which provides methods that perform simple queries.
In the old Web Forms application I have a GridView which is filled using as DataSource an SQL database view.
In order to have the same result in my new MVC3 application, I have two options:
1) Create a Service layer (and project MVC.Services), where I have a method that fill a new class myViewClass which contains all the fields of the SQL DB view and give it to the controller.
2) Create a class within the MVC.Data project which is directly filled by its constructor by using LINQ statements directly against the EF classes.
I read about the factory pattern and the 1st solution seems the most appropriate, however many people always suggest not to create a Service Layer if it is not needed. What is the best choice in this case?
Actually building the view model should be done in a mapping layer. Basically your controller action might look like this:
public ActionResult Index()
{
SomeDomainModel model = repository.GetSomeDomainModel();
SomeViewModel vm = Mapper.Map<SomeDomainModel, SomeViewModel>(model);
return View(vm);
}
The view model is defined in the MVC project as it is a class that is specifically designed to meet the requirements of the given view.
The Mapper.Map<TSource, TDest> method I have shown in my answer comes from AutoMapper which I use in my project but you could define any custom mapping layer you like.
The mapping layer must also be part of the MVC project as it must be aware of both your domain models and your view models in order to perform the mapping.
As far as the service layer is concerned, you could use one when you have some complex business operations which could be composed of multiple simple repository calls. But some might argue for the existence of a service layer at all. I think that both approaches have their pros and cons that must be evaluated when designing a system and most importantly take into consideration the specific context and scenario you are designing.
I'm using EF with ViewModel and AutoMapper design strategies for an MVC3 application.
I'm wondering if there is a more efficient way of creating the CRUD pages then what I'm currently doing.
My Current Process Involves:
Create the Entity
Create the ViewModel via copy paste then deleted non-required fields
Add the Entity to the Context list
Create a controller via the Visual Studio 2010 create controller wizard page.
I select a Template of Controller with read write actions and views, using Entity Framework.
I choose my model to be my ViewModel instead of my entity.
I select the appropriate context.
Now the part I part I think can be improved, I have to re-write all the CRUD methods to use AutoMapper and the Entity/ViewModel design pattern changing:
return View(db.BlockedUserViewModels.ToList());
into:
IList<BlockedUser> blockedUsers = db.BlockedUsers.ToList();
IList<BlockedUserViewModel> blockedUserVMs = AutoMapper.Mapper.Map<IList<BlockedUser>, IList<BlockedUserViewModel>>(blockedUsers);
return View(blockedUserVMs);
I have to add the same [Authorize] and roles permissions to each controller CRUD option.
This seems way overkill in workload! I'm hoping there a better solution. (I'm coming from Python/Django where it requires a single line of code to create beautiful strong CRUD pages)
It sounds like you can add a service and inject it into your controller. Then you only have to call
var model = _service.GetBlockedUsers();
each time instead of:
IList<BlockedUser> blockedUsers = db.BlockedUsers.ToList();
IList<BlockedUserViewModel> blockedUserVMs = AutoMapper.Mapper.Map<IList<BlockedUser>, IList<BlockedUserViewModel>>(blockedUsers);
This will keep your controllers light and act as a place to keep your crud logic so you don't have to repeat it everywhere.
Also, you can add the [Authorize] attribute to the controller if it applies to every action in the controller.
It really depends on how painful this is for you, but you can always use the MVC scaffolding stuff found in Nuget and written by Steven Sanderson. Investing some time could help you in the long run, but you have to figure out if it's right for you.
http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/
I am quite new to MVC. I am having the following questions, please help me clarify those questions, thanks a lot.
Q1. Where should I populate my view model? e.g. My view model is very big, and contains a lot of the dropdown listbox, multi select list and the other few complex objects. I am currently populate them inside the view model self, by passing the model through the constructor, and load all the object data within the constructor. I also see my college populate the viewmodel inside controller. so I am confusing now, coz lots of people suggest to keep the controller small and skinny.
Q2. We are using the linq2sql as data access layer, should I use the table entity in my viewmodel instead of creating separate model class? Expert said it's bad, but if create seperate model class, I basically repeat them and I also need to copy those value to linq 2sql entity every time when I want to persist data, it's not that fun, too much work.
lots of people suggest to keep the controller small and skinny.
Yes. What people mean is that the controller should not contain any logic, except for model <-> view mapping. With model I mean the "M" in MVC.
Q2. We are using the linq2sql as data access layer, should I use the table entity in my viewmodel instead of creating separate model class? Expert said it's bad, but if create seperate model class, I basically repeat them and I also need to copy those value to linq 2sql entity every time when I want to persist data, it's not that fun, too much work.
No. You should not. Read my answer here: ASP.NET MVC Where to put custom validation attributes
Use a mapping framework for the model -> viewmodel conversion.
Update:
From what I understand, you suggest to assembly the viewmodel inside the controller (I mean call the business layer or repository to get my data) and use controller to call the business logic dealing with the data, am I right?
yes. The controller is really a glue between your business layer / repositories and your views. The views (and view models) should know nothing about them and the business layer / repositories should know nothing about the controller/view.
The controller was created for just that purpose. To create an abstraction between the user interface layer and the lower layers. Hence the only code that should exist in the controller is to make that possible (and therefore following the Single Responsibility Principle)
If you start adding that logic into your view models you start to add coupling between the lower layers and the user interface layer. Doing any changes in the lower layers will therefore also affect all your view models (instead of just the controller
your viewmodel should be a poco, and should most certainly not be handling the mapping of the model. if you don't want to map your model to your viewmodel in the controller i would suggest you look at something like automapper. it makes it easy.
once you've mapped from your model to your viewmodel, any extra properties that need to be set such as your lists should be set in the controller.
as i stated previously, definitely don't tie your viewmodel to your current orm or table structure. you never know what might need to be refactored, and if you can handle it via an automapper mapping instead of changing your view and viewmodel then you've saved yourself a significant amount of time.
From inside to outside, these are our MVC app layers:
MS SQL / Tables / Views / Stored Procs
Entity Framework 4.1 (ORM) with POCO generation
Repository
Service (retrieve) and Control Functions (Save)
Routing -> Controller -> Razor View
(client) JQuery Ajax with Knockout.js (MVVM)
Everything is fine until I need to create a single ViewModel for step 5 to feed both the Razor view as well as the JSON/Knockout ViewModel:
Header that includes all Drop down list options and choices for the fields below
Items - an array of whatever we send to the client that becomes the ViewModel
Since the Controller won't have access to the Repository directly, does this mean I create a service for each and every view that allows editing content? I'll need to get the POCO from the repository plus all options for each field type as needed.
It just seems redundant to create separate services for each view. For example, a viewModel to edit an address and a separate viewModel to edit a real estate property that also has an address. We could have a dozen forms that edit the same address POCO.
To make this question easier to answer, is allowing the Controller direct access to the repositories a leaky abstraction?
Well, so are your controllers going to have code that translates POCOs from Entity Framework into separate view model objects?
If so, then you should move that code to a separate class, and follow the single-responsibility principle. Whether that class is in the "service layer" or not is up to you. And whether you use AutoMapper or not is up to you. But these kind of data mappers should not be part of the controller logic; controllers should be as dumb as possible.
OK, now let's ignore the data mapping problem, and pretend you could always use your POCOs directly as view models. Then you would still want a service layer, because it would translate between
userService.GetByUserName("bob")
in your dumb controller, and implement that in a specific manner by returning
userRepository.Users.Single(u => u.UserName == "bob")
Putting these together, your UserController ends up taking in IUserService and IUserDataMapper dependencies, and the code is super-dumb, as desired:
public ActionResult ShowUserPage(string userName)
{
var user = userService.GetByUserName(userName);
var viewModel = userDataMapper.MakeViewModel(user);
return View(viewModel);
}
You can now test the controller with stubs for both dependencies, or stub out IUserDataMapper while you mock IUserService, or vice-versa. Your controller has very little logic, and has only one axis of change. The same can be said for the user data-mapper class and the user service class.
I was reading an article this morning that you might find somewhat illuminating on these architectural matters. It is, somewhat condescendingly, titled "Software Development Fundamentals, Part 2: Layered Architecture." You probably won't be able to switch from a database application model to the persistent-ignorant model the article describes and suggests. But it might point you in the right direction.
i personally always inject the repository/repositories into the controller. i'm not sure why you would want to have a service layer between the repository and the controller. if anything you would use specifications.
once you've done that, check out automapper. its a mapper that, once properly configured, can map your domain model to your viewmodel, and back again.