ViewModel Best Practices - asp.net-mvc

From this question, it looks like it makes sense to have a controller create a ViewModel that more accurately reflects the model that the view is trying to display, but I'm curious about some of the conventions.
Basically, I had the following questions:
I normally like to have one class/file. Does this make sense with a ViewModel if it is only being created to hand off data from a controller to a view?
If a ViewModel does belong in its own file, and you're using a directory/project structure to keep things separate, where does the ViewModel file belong? In the Controllers directory?
That's basically it for now. I might have a few more questions coming up, but this has been bothering me for the last hour or so, and I can seem to find consistent guidance elsewhere.
EDIT:
Looking at the sample NerdDinner app on CodePlex, it looks like the ViewModels are part of the Controllers, but it still makes me uncomfortable that they aren't in their own files.

I create what I call a "ViewModel" for each view. I put them in a folder called ViewModels in my MVC Web project. I name them after the controller and action (or view) they represent. So if I need to pass data to the SignUp view on the Membership controller I create a MembershipSignUpViewModel.cs class and put it in the ViewModels folder.
Then I add the necessary properties and methods to facilitate the transfer of data from the controller to the view. I use the Automapper to get from my ViewModel to the Domain Model and back again if necessary.
This also works well for composite ViewModels that contain properties that are of the type of other ViewModels. For instance if you have 5 widgets on the index page in the membership controller, and you created a ViewModel for each partial view - how do you pass the data from the Index action to the partials? You add a property to the MembershipIndexViewModel of type MyPartialViewModel and when rendering the partial you would pass in Model.MyPartialViewModel.
Doing it this way allows you to adjust the partial ViewModel properties without having to change the Index view at all. It still just passes in Model.MyPartialViewModel so there is less of a chance that you will have to go through the whole chain of partials to fix something when all you're doing is adding a property to the partial ViewModel.
I will also add the namespace "MyProject.Web.ViewModels" to the web.config so as to allow me to reference them in any view without ever adding an explicit import statement on each view. Just makes it a little cleaner.

Separating classes by category (Controllers, ViewModels, Filters etc.) is nonsense.
If you want to write code for the Home section of your website (/) then create a folder named Home, and put there the HomeController, IndexViewModel, AboutViewModel, etc. and all related classes used by Home actions.
If you have shared classes, like an ApplicationController, you can put it at the root of your project.
Why separate things that are related (HomeController, IndexViewModel) and keep things together that have no relation at all (HomeController, AccountController) ?
I wrote a blog post about this topic.

I keep my application classes in a sub folder called "Core" (or a seperate class library) and use the same methods as the KIGG sample application but with some slight changes to make my applications more DRY.
I create a BaseViewData class in /Core/ViewData/ where I store common site wide properties.
After this I also create all of my view ViewData classes in the same folder which then derive from BaseViewData and have view specific properties.
Then I create an ApplicationController that all of my controllers derive from. The ApplicationController has a generic GetViewData Method as follows:
protected T GetViewData<T>() where T : BaseViewData, new()
{
var viewData = new T
{
Property1 = "value1",
Property2 = this.Method() // in the ApplicationController
};
return viewData;
}
Finally, in my Controller action i do the following to build my ViewData Model
public ActionResult Index(int? id)
{
var viewData = this.GetViewData<PageViewData>();
viewData.Page = this.DataContext.getPage(id); // ApplicationController
ViewData.Model = viewData;
return View();
}
I think this works really well and it keeps your views tidy and your controllers skinny.

A ViewModel class is there to encapsulate multiple pieces of data represented by instances of classes into one easy to manage object that you can pass to your View.
It would make sense to have your ViewModel classes in their own files, in the own directory. In my projects I have a sub-folder of the Models folder called ViewModels. That's where my ViewModels (e.g. ProductViewModel.cs) live.

There are no good place to keep your models in. You can keep them in separate assembly if the project is big and there are a lot of ViewModels (Data Transfer Objects). Also you can keep them in separate folder of the site project. For example, in Oxite they are placed in Oxite project which contains a lot of various classes too. Controllers in Oxite are moved to separate project and views are in separate project too.
In CodeCampServer ViewModels are named *Form and they are placed in UI project in Models folder.
In MvcPress project they are placed in Data project, which also contains all code to work with database and a bit more (but I didn't recommend this approach, it's just for a sample)
So you can see there are many point of view. I usually keep my ViewModels (DTO objects) in the site project. But when I have more than 10 models I prefer to move them to separate assembly. Usually in this case I'm moving controllers to separate assembly too.
Another question is how to easily map all data from model to your ViewModel. I suggest to have a look at AutoMapper library. I like it very much, it does all dirty work for me.
And I also I suggest to look at SharpArchitecture project. It provides very good architecture for projects and it contains a lot of cool frameworks and guidances and great community.

here's a code snippet from my best practices:
public class UserController : Controller
{
private readonly IUserService userService;
private readonly IBuilder<User, UserCreateInput> createBuilder;
private readonly IBuilder<User, UserEditInput> editBuilder;
public UserController(IUserService userService, IBuilder<User, UserCreateInput> createBuilder, IBuilder<User, UserEditInput> editBuilder)
{
this.userService = userService;
this.editBuilder = editBuilder;
this.createBuilder = createBuilder;
}
public ActionResult Index(int? page)
{
return View(userService.GetPage(page ?? 1, 5));
}
public ActionResult Create()
{
return View(createBuilder.BuildInput(new User()));
}
[HttpPost]
public ActionResult Create(UserCreateInput input)
{
if (input.Roles == null) ModelState.AddModelError("roles", "selectati macar un rol");
if (!ModelState.IsValid)
return View(createBuilder.RebuildInput(input));
userService.Create(createBuilder.BuilEntity(input));
return RedirectToAction("Index");
}
public ActionResult Edit(long id)
{
return View(editBuilder.BuildInput(userService.GetFull(id)));
}
[HttpPost]
public ActionResult Edit(UserEditInput input)
{
if (!ModelState.IsValid)
return View(editBuilder.RebuildInput(input));
userService.Save(editBuilder.BuilEntity(input));
return RedirectToAction("Index");
}
}

We throw all of our ViewModels in the Models folder (all of our business logic is in a separate ServiceLayer project)

Personally I'd suggest if the ViewModel is anything but trivial then use a separate class.
If you have more than one view model then I suggest it make sense to partition it in at least a directory. if the view model is later shared then the name space implied in the directory makes it easier to move to a new assembly.

In our case we have the Models along with the Controllers in a project separate from the Views.
As a rule of thumb, we've tried to move and avoid most of the ViewData["..."] stuff to the ViewModel thus we avoid castings and magic strings, which is a good thing.
The ViewModel as well holds some common properties like pagination information for lists or header information of the page to draw breadcrumbs and titles. At this moment the base class holds too much information in my opinion and we may divide it in three pieces, the most basic and necessary information for 99% of the pages on a base view model, and then a model for the lists and a model for the forms that hold specific data for that scenarios and inherit from the base one.
Finally, we implement a view model for each entity to deal with the specific information.

code in the controller:
[HttpGet]
public ActionResult EntryEdit(int? entryId)
{
ViewData["BodyClass"] = "page-entryEdit";
EntryEditViewModel viewMode = new EntryEditViewModel(entryId);
return View(viewMode);
}
[HttpPost]
public ActionResult EntryEdit(Entry entry)
{
ViewData["BodyClass"] = "page-entryEdit";
#region save
if (ModelState.IsValid)
{
if (EntryManager.Update(entry) == 1)
{
return RedirectToAction("EntryEditSuccess", "Dictionary");
}
else
{
return RedirectToAction("EntryEditFailed", "Dictionary");
}
}
else
{
EntryEditViewModel viewModel = new EntryEditViewModel(entry);
return View(viewModel);
}
#endregion
}
code in view model:
public class EntryEditViewModel
{
#region Private Variables for Properties
private Entry _entry = new Entry();
private StatusList _statusList = new StatusList();
#endregion
#region Public Properties
public Entry Entry
{
get { return _entry; }
set { _entry = value; }
}
public StatusList StatusList
{
get { return _statusList; }
}
#endregion
#region constructor(s)
/// <summary>
/// for Get action
/// </summary>
/// <param name="entryId"></param>
public EntryEditViewModel(int? entryId)
{
this.Entry = EntryManager.GetDetail(entryId.Value);
}
/// <summary>
/// for Post action
/// </summary>
/// <param name="entry"></param>
public EntryEditViewModel(Entry entry)
{
this.Entry = entry;
}
#endregion
}
projects:
DevJet.Web ( the ASP.NET MVC web
project)
DevJet.Web.App.Dictionary ( a
seperate Class Library project)
in this project, i made some folders like:
DAL,
BLL,
BO,
VM (folder for view models)

Create a view model base class which has commonly required properties like result of the operation and contextual data ,you can also put current user data and roles
class ViewModelBase
{
public bool HasError {get;set;}
public string ErrorMessage {get;set;}
public List<string> UserRoles{get;set;}
}
In base controller class have a method like PopulateViewModelBase() this method will fill up the contextual data and user roles.
The HasError and ErrorMessage , set these properties if there is exception while pulling data from service/db. Bind these properties on view to show error.
User roles can be used to show hide section on view based on roles.
To populate view models in different get actions , it can be made consistent by having base controller with abstract method FillModel
class BaseController :BaseController
{
public PopulateViewModelBase(ViewModelBase model)
{
//fill up common data.
}
abstract ViewModelBase FillModel();
}
In controllers
class MyController :Controller
{
public ActionResult Index()
{
return View(FillModel());
}
ViewModelBase FillModel()
{
ViewModelBase model=;
string currentAction = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString();
try
{
switch(currentAction)
{
case "Index":
model= GetCustomerData();
break;
// fill model logic for other actions
}
}
catch(Exception ex)
{
model.HasError=true;
model.ErrorMessage=ex.Message;
}
//fill common properties
base.PopulateViewModelBase(model);
return model;
}
}

Related

Different controllers for views on the same folder on asp.net MVC4

I've been researching about this. I found "MVCs areas" but I still couldn't do what I'm looking for.
MY VIEWS:
Views/
Student/Course
Student/Information
Student/Status
Student/GeneralSituation
etc, etc...
CONTROLLERS:
Controllers/Student
What I want to do is:
I don't want to have All the code from a lot of views in just one "Student" controller.
Any tip regarding how I can "split" my controllers in several files?
I'm just looking at the simplest approach, I don't want to make big modifications to my project.
I'm using MVC4.
Thanks in advance!..
PnP
Why not just make partial Controller classes and thus split one controller over a bunch of physical files?
Also, what do you mean by "the code from a lot of views"? Are you using a separate service layer and doing the business logic in there, because that's best practice. Controllers are meant to be very lightweight with code along the lines of this:
public ActionMethod DoSomething()
{
StudentViewModel vm = _studentService.GetSomeData();
return View(vm);
}
you can do a partial class StudentController:
your folder/files would look like this:
Controllers
StudentController
StudentController.Status.cs
StudentController.GeneralSituation.cs
StudentController.Course.cs
The code would be:
StudentController.Status.cs:
public partial class StudentController
{
[Actions relevant for Status of a student]
}
StudentController.GeneralSituation.cs:
public partial class StudentController
{
[Actions relevant for General Situation of a student]
}
Any reason why Area's don't work? From what you described, I don't really see why they wouldn't.
- Areas
- Students
- Controllers
HomeController Handles base /Students/ route
InformationController ~/Students/Information/{action}/{id}
StatusController ~/Students/Status/{action}/{id}
...
- Models
- Views
Home/
Information/
Status/
...
Shared/ Stick common views in here
If you're set on one monster controller (or partials), your controller should have very little actual 'View code' in it. Leave all that to view models - the controller just passes in the needed resources to build view data, keeping controllers thin.
Ie,
public class StudentController
{
...
// Actually I prefer to bind the id to a model and handle 404
// checking there, vs pushing that boiler plate code further down
// into the controller, but this is just a quick example.
public ActionResult Information(int id)
{
return View(new InformationPage(this.StudentService, id));
}
}
Then, InformationPage is one of your models that will handle building out all information applicable to that view.
public class InformationPage
{
public Student Student { get; set; }
public InformationPage(StudentService service, int studentId)
{
Student = service.FindStudent(studentId);
... Other view data ...
}
}

IoC in MVC: How do I handle the flow of service objects from controllers through models?

I am using MVC3 and have implemented IoC to provide service/manager objects to controllers through constructor arguments. These in turn, may get passed to models.
The problem I am having is that passing these objects all over the place can get cumbersome.
Example:
public CartController(
ICartManager cartManager,
IProductManager productManager,
IUpsellManager upsellManager,
IAccountManager accountManager,
... more ...)
{
... store to class variables ...
}
public ActionResult Index()
{
...
CartModel model = new CartModel(
cartManager,
accountManager,
upsellManager,
productManager,
... );
return View(model);
}
And the cart model may have sub models to which it must pass parameters. As you see, it all gets very cumbersome. I've ready if you have so many constructor arguments, your controller may be doing too much, but this is a complex page, and the site will contain many other complex pages. I don't want to have to pass so many things, but how can I not pass them and maintain a control?
I'm tempted to use the DependencyResolver in the models but that defeats the purpose and Service Locator is known anti-pattern.
How can I avoid passing so many arguments without giving up the benefits of IoC?
The advantage of using dependency inversion is to enforce clear separation of responsibilities between the various roles in the application. The Controller it is really just interested in dealing with HTTP Request and the HTTP Response. All other logic is dealt with elsewhere and the controller delegates to types it is dependent upon to do this work. This pattern is then repeated for each function in the system. One way to detect that this pattern isn't being followed is to use the new operator to create a type and pass in dependencies to the constructor. This is the job for the IoC container you are using.
I would suggest swapping the logic around and having the CartManager return a CartModel for the view. This could be some kind of DTO which is specific to the view. How the data gets put in to this object is the responsibility of the CartManager. If it needs the use of other services they can be injected in to it's constructor.
public CartController : Controller
private ICartManager _cartManager;
public CartController(ICartManager cartManager) {
_cartManager = cartManager;
}
[HttpGet]
public ActionResult Index(int userId) {
var model = _cartManager.CreateCart(int userId);
return View(model);
}
...
public class CartManager : ICartManager {
IDbService _dbService;
public CartManager(IDbService dbService){
_dbService = dbSerivce;
}
CartModel CreateCart(int userId) {
var user = _dbService.FindTheUser(int user);
var cartModel = new CartModel { userId = userId, Name = user.Name };
/* other stuff to map up a cartmodel
return cartModel;
}
}
This idea is not just specific to the use of IoC containers but is also good practice for creating MVC applications. I also found this post by Rob Ashton to be a good guide.
I like using a factory pattern for this scenario, where you need to instantiate class B (CartModel) within class A (CartController), and there are a bunch of dependencies in B that A doesn't need.
public CartController(
ICartModelFactory factory
... more ...)
{
... store to class variables ...
}
public ActionResult Index()
{
...
CartModel model = factory.GetInstance(
... );
return View(model);
}
You shouldn't be passing all those services to your view. What that means is that your template now has to perform actions to call this data, which complicates things (as you've seen). In addition to needless complexity, it also creates a dependency of these services in the view, and tighly couples the view to these services. If you change the services, you then have to change all the views that use it.
First thing you need to do is create a ViewModel that contains all the Data the view will need. Then, you need to find a way to map your manager classes returned data into this view. You can do it manually in the controller, or use something like AutoMapper to do the translations.
Another option is to either refactor ICartManager so that it returns all the data (your CartManager class would then have constructor injection of the other services) or create a different service that aggregates them and constructs an object that you can map to your View model.
You should never have to pass those methods around. They should always be injected into an object.

How are you populating/validating your ViewModels?

I'm curious of all of the various ways people are building their ViewModels and why they choose that method.
I can think of several ways here:
-1. Injected repository - the controller loads the model and maps to the ViewModel. Here the ViewModel constructor could take various collections to interally set for ex. in a select list such as:
public CustomerController(ISomeRepository repository)
{
_repository = repository;
}
public ActionResult Create()
{
CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes,
_repository.GetStates);
..
..
}
-2. ViewModelBuilder - Either injected or instantiated in the controller with an instance of the injected repository. Called via something like
>var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
or,
var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
-3. Directly in controller (no code required - its messy)
-4. Some other service (injected or not) that returns domain model which the controller then maps or a ViewModel (anyone doing this to return a view model that isn't specifically named/noted as a ViewModel builder class?)
public JobCreateViewModel BuildJobCreateViewModel(int parentId)
{
JobCreateViewModel model = new JobCreateViewModel();
model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses();
model.States=_unitOfWork.StateRepository.GetAll();
return model;
}
Now on the return trip - regarding validating your view models - are you inheriting from a base ViewModel class for standard validations, or copying your validations (ex. data annotation attributes) between all of your ViewModels, or simply relying on server side validation so it can all be validated againt your domain object?
Any others? Anything better? Why?
EDIT
Based on a link below, I did find a nice article from Jimmy Bogard on the architecture of ViewModels. While it doesn't address the question above directly, it's a great reference for anyone coming here for ViewModel information.
http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
I inject a service into the controller, not a repository, and then use AutoMapper to convert it into a view model. The benefit of the service layer in this case is that it could aggregate multiple simple operations from one or more repositories into a single operation exposing a domain model. Example:
private readonly ICustomerService _service;
public CustomerController(ICustomerService service)
{
_service = service;
}
[AutoMap(typeof(Customer), typeof(CustomerViewModel))]
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
return View(customer);
}
in this example AutoMap is a custom action filter that I can write which executes after the controller action, inspects the returned object and uses defined AutoMapper mappings to map it to the specified destination type. So the view gets the corresponding CustomerViewModel as model type. Would have been equivalent to:
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer);
return View(vm);
}
it's just that it is too much plumbing and repetitive code that could be centralized.
I would also recommend you watching the putting your controllers on a diet video from Jimmy Bogard.
I just finished a project where we did a variation on #4. We had a service class injected into the controller. The service class held dependencies on the repository and a model builder class (we called it model factory).
The controller called into the service class, which handled business validation logic, and then fetched view models from the appropriate factory. The models themselves relied on data annotations for input validation.
It worked really well for our team. There was enough separation of concerns to allow the devs to do their work without affecting one another, but it was manageable enough to understand what was going on.
It's the first time we tried it and we'll be sticking with it. I'm interested to see how others respond.
Our method is to inject the repository in to the controller and map it to the ViewModel using Automapper http://automapper.org/. Our ViewModels contain data annotation attributes to allow the validation to occur on the client.
We call methods on the repository which return Domain objects (Entity Framework). The domain objects are mapped to the ViewModel. We tend to use the same ViewModel for edits and adds so the data annotations are needed once. In its simplest form it looks like the following code:
public ActionResult List(int custId, int projId)
{
var users = _userRepository.GetByCustomerId(custId);
var userList = Mapper.Map<IEnumerable<CMUser>, IEnumerable<UserListViewModel>>(users);
return View(userList);
}
I use a service layer that hides the domain model from the controller returning ViewModels from the service methods. This allows me to make changes to the domain model without impacting the client.

Correct use of Model vs Controller in MVC / ASP.NET MVC

I have a Service class with a method called GetProducts(). That encapsulates business logic and calls the repository to get a list of products.
My MVC view wants to show that list of products as an MVC SelectList. Where is the correct place for that logic to go. I seem to have 3 options:
Model
The Model should expose a property called ProductSelectList. When the getter of this property is called by the View, the Model should call Service.GetProducts() and convert the result to a SelectList before passing it on.
Plausible argument: The Model should make calls to business logic and the repository. The View should merely render predetermined data. The Controller should not be involved, save for passing contextual data to the Model.
View
The View should contain code that calls Service.GetProducts() directly and converts the result to a SelectList inline.
Plausible argument: The View should call for this data directly as it is specifically for use on the View. There is no need to involve the Model or Controller, as we are calling an abstracted Service method anyway, so anything else just adds extra overhead.
Controller
The Controller should make the call to Service.GetProducts(), convert the results to a SelectList and pass it through to the Model, which should contain a simple ProductSelectList property. The View will access this property for rendering.
Plausible argument: The Controller knows which parameters to provide to the Service method, so it should make the call. The Model should be a simple placeholder for data, filled by the Controller. The View's job is to simply render the data from the Model.
I have a feeling that the correct answer is Model, but the other two make some reasonable points. Perhaps I've muddied the waters by already having a Service class that's separate to the Model?
Would anybody care to share their opinion? Is this just a matter of taste?
I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).
I have my views dumb and only displaying data.
I have my View Models store the information that the View will need, occasionally exposing 'get only' properties that format other properties into a nicer format. If my model needs access to my services, then I feel I'm doing something wrong.
The controllers arrange and gather all the information together (but do no actual work, that is left for the services.
In your example, I would have my controller action similar to:
public ActionResult Index()
{
IndexViewModel viewModel = new IndexViewModel();
viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");
return View(viewModel);
}
and my view model similar to:
public class IndexViewModel()
{
public SelectList ProductSelectList { get; set; }
public int ProductID { get; set; }
}
With the appropriate part of the view looking like:
#Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList);
This way I'm content that I know where to look if there is an issue with anything and everything has a very specific place.
However, there is no correct way as seems always to be the case with these things. Stephen Walther has a good blog series on MVC tips. In one he talks about the View Model emphasis and although not a SelectList he populates, the SelectList is still data in much the same way his list of products is.
In a classic MVC architecture your Model shouldn't be much more than a container for your view data hence the reason it's often called a ViewModel. A ViewModel is different from the Entity Model(s) that your service layer manages.
Your controller is then responsible for populating your ViewModel from the entity model(s) returned by your service layer.
Due to convenience some developers will use their service layer entities directly in their ViewModels but long term that can lead to headaches. One way around that is to use a tool such as AutoMapper to automate the shuffling of data to and from your ViewModel and entity models.
Here's what a controller might look like. Notice that data such as the SSN does not get exposed to the view since there is a mapping from your Entity Models to your View Model.
public class Customer : IEntity
{
public string CustomerID { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class CustomerEditViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string PhoneNumber { get; set; }
}
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit ()
{
Customer customer = _customerService.GetCustomer (User.Identity.Name);
var model = new CustomerEditViewModel ()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Address1 = customer.Address.Address1,
Address2 = customer.Address.Address2,
Country = customer.Address.Country,
City = customer.Address.City,
State = customer.Address.State,
Zip = customer.Address.Zip,
PhoneNumber = customer.Address.PhoneNumber,
};
return View (model);
}
}
You're right that there are a number of ways to handle this, and that's even before considering variations like MVP, MVVM, et cetera. Since you're asking about ASP.Net MVC in particular, I will defer to Microsoft:
An MVC model contains all of your application logic that is not
contained in a view or a controller. The model should contain all of
your application business logic, validation logic, and database access
logic. For example, if you are using the Microsoft Entity Framework to
access your database, then you would create your Entity Framework
classes (your .edmx file) in the Models folder.
A view should contain only logic related to generating the user
interface. A controller should only contain the bare minimum of logic
required to return the right view or redirect the user to another
action (flow control). Everything else should be contained in the
model.
In general, you should strive for fat models and skinny controllers.
Your controller methods should contain only a few lines of code. If a
controller action gets too fat, then you should consider moving the
logic out to a new class in the Models folder.
Source
I would say your call belongs in the Model.
One thing to keep in mind is that the SelectList class is specific to MVC only. So in my opinion it shouldn't be included in any business logic, and model classes fall into that category. Therefore your select list should be a part of a view model class instead.
This is the way it works in my projects:
Controller method is called
Controller uses repository (business logic, in other words) to get model data
Controller converts the model data if necessary and creates a view model object
Controller passes the view model to the view
The view displays the data in the view model with limited logic to show or hide things, etc
I'd go with option 3. In general, I'll construct my MVC apps such that the controller makes a call to the service to return a model (or collection of models) which are then passed to the view.
I generally keep my models very thin. They are a flattened representation of the data with validation attributes and that's it. I use a service (or model builder) layer to construct the models and do business logic on them. Some folks embed that into the model, but I find that makes for a messy project.
You definitely don't want the view making any calls to your services.
Update...
I'm assuming that this SelectList is your model. If instead it's a part of your model, then you're right, you should put it in your model. I generally don't like to make it a method call, though. I'd have a property on my model:
public SelectList Products { get; set; }
And have my service or model builder class actually populate it. I don't usually have any data-oriented methods on my models.
I'm going with option 1.
Models are the place to make calls to business logic, et cetera.
View - Should display only what the ViewModel already has been populated with.
Controller - the job of the Controller is to direct the traffic coming in (from Web requests) to the Logic that is responsible for handling the request. Hence the term 'controller'.
There are always exceptions to these, but the best place (structurally) is the Model.
I had this problem when I started into MVC and came up with this solution.
The controller talks to a Service Layer. The service layer contains my Domain models and does all the processing for request from the Controllers. The service layer also returns ViewModels to satisfy requests from the controller.
The service layer calls a repository and gets the entities it will need to build the ViweModels. I often use Automapper to populate the ViewModel or collections within the view model.
So, my view models contain all that is needed by the View, and the Controller is doing nothing but handling request and forwarding them to the appropriate service handler.
I don't see a problem with having view specific items like SelectLists in the view Model either.
None of the above.
In my web layer I basically just have html and javascript views. The model shouldn't leak into the view and neither should the services.
I also have an Infrastructure layer which binds the services and model to the views. In this layer there are ViewModels, which are classes that represent what will be displayed on the screen, Mappers, which do the work getting data from services/model and mapping it to the view model, and Tasks, which perform tasks such as Saving, Updating and Deleting data.
It is possible to put a lot of this infrastructure in the Controllers, similar to the example Todd Smith has given above, but I find for anything other than trivial views the Controller becomes littered with code to load data and populate view models. I prefer a dedicated single responsibility mapper class for each view model. Then my controller will look something like
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit (int id)
{
return View (CustomerEditMapper.Map(id));
}
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Save(CustomerEditViewModel model)
{
var errors = CustomerEditUpdatorCommand.Execute(model);
ModelState.AddErrors(errors);
return View ();
}
}
I'm torn between option 1 and option 3. I've ruled option 2 out completely as to me that's polluting the view with procedure calls not just presentation layer work.
Personally I would do it in the model and the getter would call the Service layer but I also subscribe to the belief that the model should only contain the information the view needs to render the page, by not fully containing the data in the model at the time you pass it to the view you are breaking this.
Another option here though would be to avoid tightly coupling the view and model by putting a Dictionary of the Products into the view through a Service Call then using the view to transform the Dictionary to a SelectList but this also gives you the ability to just output the information as well.
I think this boils down to a preference as to where you are happy having your logic.

Fetching data within an ASP.NET MVC ViewModel class?

For those that create ViewModels (for use by typed views) in ASP.NET MVC, do you prefer to fetch the data from a service/repository from within the ViewModel, or the controller classes?
For example, we started by having ViewModels essentially being DTOs and allowing our Controllers to fetch the data (grossly oversimplified example assumes that the user can only change employee name):
public class EmployeeViewModel
{
public String Name; //posted back
public int Num; //posted back
public IEnumerable<Dependent> Dependents; //static
public IEnumerable<Spouse> Spouses; //static
}
public class EmployeeController()
{
...
public ActionResult Employee(int empNum)
{
Models.EmployeeViewModel model = new Models.EmployeeViewModel();
model.Name = _empSvc.FetchEmployee(empNum).Name;
model.Num = empNum;
model.Dependents = _peopleSvc.FetchDependentsForView(empNum);
model.Spouses = _peopleSvc.FetchDependentsForView(empNum);
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(Models.EmployeeViewModel model)
{
if (!_empSvc.ValidateAndSaveName(model.Num, model.Name))
{
model.Dependents = _peopleSvc.FetchDependentsForView(model.Num);
model.Spouses = _peopleSvc.FetchDependentsForView(model.Num);
return View(model);
}
this.RedirectToAction(c => c.Index());
}
}
This all seemed fine until we started creating large views (40+ fields) with many drop downs and such. Since the screens would have a GET and POST action (with POST returning a view if there was a validation error), we'd be duplicating code and making ViewModels larger than they probably should be.
I'm thinking the alternative would be to Fetch the data via the Service within the ViewModel. My concern is that we'd then have some data populated from the ViewModel and some from the Controller (e.g. in the example above, Name would be populated from the Controller since it is a posted value, while Dependents and Spouses would be populated via some type of GetStaticData() function in the ViewModel).
Thoughts?
I encountered the same issue. I started creating classes for each action when the code got too big for the action methods. Yes you will have some data retrieval in classes and some in the controller methods. The alternative is to have all the data retrieval in classes, but half the classes you won't really need, they will have been created for consistency sake or have all the data retrieval in the controller methods, but again, some of those methods will be too complex and needed to have been abstracted into classes... so pick your poison. I would rather have a little inconsistency and have the right solution for the job.
As for putting behavior into the ViewModel, I don't, the point of the ViewModel is to be a thin class for setting and extracting values from the View.
There have been cases where I've put conversion methods in the ViewModel. For instance I need to convert the ViewModel to the corresponding entity or I need to load the ViewModel with data from the Entity.
To answer your question, I prefer to retrieve data from with in the controller/action methods.
Typically with DropDowns, I create a dropdown service. DropDowns tend to be the same data that spans views. With the dropdowns in a service I can use them on other views and/or Cache them.
Depending on the layout, 40 plus fields could create a cluttered view. Depending the type of data, I would try to span that many fields across multiple views with some sort of tabbed or wizard interface.
There's more than that ;-) You can fetch in model binder or action filter. For the second option, check Jimmy Bogard's blog somewhere around here. I personally do it in model binders. I use ViewModel like this: My custom ASP.NET MVC entity binding: is it a good solution?. It is processed by my custom model binder:
public object BindModel(ControllerContext c, BindingContext b)
{
var id = b.ValueProvider[b.ModelName]; // don't remember exact syntax
var repository = ServiceLocator.GetInstance(GetRepositoryType(b.ModelType));
var obj = repository.Get(id);
if (obj == null)
b.ModelState.AddModelError(b.ModelName, "Not found in database");
return obj;
}
public ActionResult Action(EntityViewModel<Order> order)
{
if (!ModelState.IsValid)
...;
}
You can also see an example of model binder doing repository access in S#arp Architecture.
As for static data in view models, I'm still exploring approaches. For example, you can have your view models remember the entities instead of lists, and
public class MyViewModel
{
public MyViewModel(Order order, IEmployeesSvc _svc)
{
}
public IList<Employee> GetEmployeesList()
{
return _svc.GetEmployeesFor(order.Number);
}
}
You decide how you inject _svc into ViewModel, but it's basically the same as you do for controller. Just beware that ViewModel is also created by MVC via parameterless constructor, so you either use ServiceLocator or extend MVC for ViewModel creation - for example, inside your custom model binder. Or you can use Jimmy Bogard's approach with AutoMapper which does also support IoC containers.
The common approach here is that whenever I see repetative code, I look to eliminate it. 100 controller actions doing domain-viewmodel marshalling plus repository lookup is a bad case. Single model binder doing it in generic way is a good one.
I wouldn't be fetching data from the database in your ViewModel. The ViewModel exists to promote separation of concerns (between your View and your Model). Tangling up persistance logic in there kind of defeats the purpose.
Luckily, the ASP.NET MVC framework gives us more integration points, specifically the ModelBinder.
I've got an implementation of a generic ModelBinder pulling information from the service layer at:-
http://www.iaingalloway.com/going-further-a-generic-servicelayer-modelbinder
It doesn't use a ViewModel, but that's easily fixed. It's by no means the only implementation. For a real-world project, you're probably better off with a less generic, more customised solution.
If you're diligent, your GET methods don't even need to know that the service layer exists.
The solution probably looks something like:-
Controller action method:-
public ActionResult Details(MyTypeIndexViewModel model)
{
if( ModelState.IsValid )
{
return View(model);
}
else
{
// Handle the case where the ModelState is invalid
// usually because they've requested MyType/Details/x
// and there's no matching MyType in the repository
// e.g. return RedirectToAction("Index")
}
}
ModelBinder:-
public object BindModel
(
ControllerContext controllerContext,
BindingContext bindingContext
)
{
// Get the Primary Key from the requestValueProvider.
// e.g. bindingContext.ValueProvider["id"]
int id = ...;
// Get an instance of your service layer via your
// favourite dependancy injection framework.
// Or grab the controller's copy e.g.
// (controllerContext.Controller as MyController).Service
IMyTypeService service = ...;
MyType myType = service.GetMyTypeById(id)
if (myType == null)
{
// handle the case where the PK has no matching MyType in the repository
// e.g. bindingContext.ModelState.AddModelError(...)
}
MyTypeIndexViewModel model = new MyTypeIndexViewModel(myType);
// If you've got more repository calls to make
// (e.g. populating extra fields on the model)
// you can do that here.
return model;
}
ViewModel:-
public class MyTypeIndexViewModel
{
public MyTypeIndexViewModel(MyType source)
{
// Bind all the properties of the ViewModel in here, or better
// inherit from e.g. MyTypeViewModel, bind all the properties
// shared between views in there and chain up base(source)
}
}
Build your service layer, and register your ModelBinder as normal.
Here's another solution: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx
Main points there:
Mapping is done by a mediator - in this case it is AutoMapper but it can be your own class (though more to code). This keeps both Domain and ViewModel concentrated on the domain/presentation logic. The mediator (mapper) will contain (mostly automatic) logic for mapping, including injected services.
Mapping is applied automatically, all you do is tell the action filter the source/destination types - very clean.
(Seems to be important for you) AutoMapper supports nested mappings/types, so you can have your ViewModel combined of several independent view models, so that your "screen DTO" is not messy.
Like in this model:
public class WholeViewModel
{
public Part1ViewModel ModelPart1 { get; set; }
public Part2ViewModel ModelPart2 { get; set; }
}
you re-use mappings for specific parts of your View, and you don't write any new line of code, since there're already mappings for the partial view models.
If you don't want AutoMapper, you have have IViewModelMapper interfaces, and then your IoC container will help your action filter to find appropriate
container.Resolve(typeof(IViewModelMapper<>).MakeGenericType(mysourcetype, mydesttype))
and it will also provide any required external services to that mapper (this is possible with AutoMapper, too). But of course AutoMapper can do recursions and anyway, why write additional AutoMapper ;-)
Consider passing your services into the custom ViewModel on its constructor (ala Dependency Injection). That removes the model population code from your controller and allows it to focus on controlling the logical flow of the application. Custom ViewModels are an ideal place to abstract the preparation of things like SelectLists that your droplists will depend on.
Lots of code in the controller for things like retrieving data isn't considered a best practice. The controller's primary responsibility is to "control" the flow of the application.
Submitting this one late... Bounty is almost over. But...
Another mapper to look at is Automapper: http://www.codeplex.com/AutoMapper
And overview on how to use it: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx
I really like it's syntax.
// place this somewhere in your globals, or base controller constructor
Mapper.CreateMap<Employee, EmployeeViewModel>();
Now, in your controller, I would use multiple viewmodels. This enforces DRY by allowing you to reuse those viewmodels elsewhere in your application. I would not bind them all to 1 viewmodel. I would refactor to something like:
public class EmployeeController()
{
private IEmployeeService _empSvc;
private ISpouseService _peopleSvc;
public EmployeeController(
IEmployeeService empSvc, ISpouseService peopleSvc)
{
// D.I. hard at work! Auto-wiring up our services. :)
_empSvc = empSvc;
_peopleSvc = peopleSvc;
// setup all ViewModels here that the controller would use
Mapper.CreateMap<Employee, EmployeeViewModel>();
Mapper.CreateMap<Spouse, SpouseViewModel>();
}
public ActionResult Employee(int empNum)
{
// really should have some validation here that reaches into the domain
//
var employeeViewModel =
Mapper.Map<Employee, EmployeeViewModel>(
_empSvc.FetchEmployee(empNum)
);
var spouseViewModel =
Mapper.Map<Spouses, SpousesViewModel>(
_peopleSvc.FetchSpouseByEmployeeID(empNum)
);
employeeViewModel.SpouseViewModel = spouseViewModel;
return View(employeeViewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(int id, FormCollection values)
{
try
{
// always post to an ID, which is the employeeID
var employee = _empSvc.FetchEmployee(id);
// and bind using the built-in UpdateModel helpers.
// this will throw an exception if someone is posting something
// they shouldn't be posting. :)
UpdateModel(employee);
// save employee here
this.RedirectToAction(c => c.Index());
}
catch
{
// check your domain model for any errors.
// check for any other type of exception.
// fail back to the employee screen
RedirectToAction(c => c.Employee(id));
}
}
}
I generally try to stay away from saving multiple entities on a controller action. Instead, I would refactor the employee domain object to have AddSpouse() and SaveSpouse() methods, that would take an object of Spouse. This concept is known as AggregateRoots, controlling all dependancies from the root - which is the Employee() object. But, that is just me.

Resources