ASP.NET MVC Model vs ViewModel - asp.net-mvc

OK, I have been hearing discussion about "ViewModels" in regards to MS's ASP.NET MVC.
Now, that is intended to be a specific kind of Model, correct? Not a specific kind of View.
To my understanding, it's a kind of Model that has a specific purpose of interacting with the View? Or something like that?
Some clarification would be appreciated.

Essentially Model and View Model are both simple classes with attributes.
The main objective of these classes are to describe (to "Model") an object for their respective audiences that are respectively the controller and the view.
So you are completely right when you say
To my understanding, it's a kind of
Model that has a specific purpose of
interacting with the View
So, while Model classes are effectively Domain Entities that your application interact with, View Models are simple classes that your views interact with.
Hope it helps :)
Update:
Microsoft has developed a specialized version of the Presentation Pattern by Martin fowler largely based on the Model-View-Controller and called it Model-View-ViewModel (MVVM) for PF application. This pattern is targeted at modern UI development platforms where UI developers have different requirements based more on business logic than traditional developers. Have a look here for a bit of theory

In the simplest of terms, I like to think of the following:
Model: Strictly looks and feels like your data model. For all intents and purposes it is only a class representation of your data model. It has no knowledge of your View or any elements within your View. That said, it should not contain any attribute decorators (ie; Required, Length, etc.) that you would use for your View.
View Model: Serves as a data-binder between your View and your Model and in many cases, is also a wrapper for your Model. It would be rendered useless without the View, so it typically isn't reusable across multiple Views and Controllers like a standard Model is.
As an example, your Model may have the following properties, which are direct representations of your data source:
public string FirstName { get; set; }
public string LastName { get; set; }
Now, since your View Model is tied to your View, it may have the following property - which concatenates the Model's FirstName field and LastName field together as one string:
[Display(Name = "Customer Name")]
public string CustomerFullName { get { return String.Format("{0} {1}", myModel.FirstName, myModel.LastName) }}

I found this article a very useful resource for understanding how the "Domain Model" and "View Model" interact within an MVC application, particularly in regards to binding. Best of all includes examples instead of abstract descriptions.
"Since MVC has been released I have observed much confusion about how best to construct view models. Sometimes this confusion is not without good reason since there does not seem to be a ton of information out there on best practice recommendations. Additionally, there is not a “one size fits all” solution that acts as the silver bullet. In this post, I’ll describe a few of the main patterns that have emerged and the pros/cons of each. It is important to note that many of these patterns have emerged from people solving real-world issues."
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx

WikiPedia has a more complete description of Model vs. ModelView than you'll get in an SO answer: http://en.wikipedia.org/wiki/Model_View_ViewModel
I quote:
Model: as in the classic MVC pattern, the model refers to either (a) an object model that represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).
View: as in the classic MVC pattern, the view refers to all elements displayed by the GUI such as buttons, windows, graphics, and other controls.
ViewModel: the ViewModel is a “Model of the View” meaning it is an abstraction of the View that also serves in data binding between the View and the Model. It could be seen as a specialized aspect of what would be a Controller (in the MVC pattern) that acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model. The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.

There is a notion of a ViewModel, but it is not generally associated with Asp.net MVC. MVC uses the Model View Controller patter, where the controller handles interactions, builds up data from the Model, and then passes that data to the View for display.
ViewModels (and the Model View ViewModel pattern) is more generally associated with Silverlight and WPF. Xaml is a bit different in that the views can do two-way binding to the ViewModels, so the technology is a little different. For example, if you bind a textbox to a field, as you type into that textbox, the value of the field is updated dynamically. This sort of interaction isn't really possible in web pages since web pages are stateless.
The similarity in the two patterns is that they are both trying to separate the logic from the display. The most common use/reason for this is testing: you want to be able to perform from code (via a testing framework) all the interactions that a user will invoke via the User Interface.

Related

In asp.net-mvc, Is it wrong to move my "EditViewModel" classes outside my MVC web project?

I have an asp.net-mvc site that pretty much is a CRUD app but I also do some adds & updates outside the webview (upload from spreadsheets, etc). Based on this article, I am trying to get as much of the logic outside the MVC project into a seperate shared project so i can reuse the same code in all scenarios and I am trying to isolate and seperate my "read" viewModels that are binding to UIs for display from the "edit" viewModels that represent what is being posted to the server on a form post.
I have a number of projects in the solution (domainobjects, importexport,etc) that are shared with other solution plus the MVC project has the following directories in the MVC project
Controllers
Views
ViewModels
Scripts
EditViewModels
My ViewModels folder represents the objects that I am binding to my views (a container object that usually includes:
A domain object and
A bunch of IEnumerable of SelectListItem to populate UI dropdowns, etc
something like this:
public class OrderViewModel
{
public Order MyOrder {get;set;}
public IEnumerable<SelectListItem> OrderTypes {get;set;}
public IEnumerable<SelectListItem> Sizes {get;set;}
}
My EditViewModels folder represents the objects that i am posting from forms to the server so they are usually simpler flat objects with just primatives that i then populate a domain object with before adding or updating my database like this:
public class OrderEditViewModel
{
public int Id {get;set;}
public int OrderTypeId {get;set;}
public int SizeId {get;set;}
}
My main question is when i have a method in my Controller class that usually looks like this (simplified):
public ActionResult Update(OrderEditViewModel order)
{
var existingOrder = _repository.GetOrder(order.Id);
existingOrder.Name = order.Name;
existingOrder.Size = _repository.GetSize(order.SizeId);
existingOrder.Price = order.Price;
_repository.Save(existingOrder);
return Json( Result = "Success");
}
I am trying to figure out how to get as much code as possible outside the MVC project but that forces me to move all of my classes in the EditViewModel outside of the MVC project so those objects can be reused.
Does anyone see anything wrong with having these "Post" data structure classed outside the MVC projecdt. Given its a "viewmodel" class it feels wrong to move it away from the view but I don't see any other way to share this code outside of the MVC project. Maybe the "viewModel" name here is just wrong possibly?
Your View Models are specific to your views, and should not be relevant to anything else. They contain things which nothing else should care about, such as your select lists. As such, they should stay in your UI.
The article appears to me to be creating a situation in which the business logic depends on the UI (or at least the UI Model.. ie View Model), and I think that is the wrong approach. The UI should be able to consume the business logic without the business logic being aware what the UI is. It could be a web site, a fat client, a mobile client, a web service, etc... By making this logic depend on your view models, you now are making any future services that are not web based depend on those.
This is, however, a simple CRUD app, and in simple CRUD apps you can often take a lot of shortcuts because it's just not worth the extra engineering effort. I wouldn't normally pass a domain object to the view directly in the View Model. But in this case it's probably the best choice.
If you want to do it "right", however, then you need to create more separation of concerns. Your domain and ui layers need more separation. You create separate view and domain models, and then map between them. This prevents the business layer from knowing anything about the UI.
I would probably create a service layer that handles your logic. For instance:
_orderService.UpdateOrder(order.Id, order.Name, order.Price);
In my case, i make a difference between read(view-)models and write-models.
Read models are very specific to the view, they can contain select lists and formatted and localized content. You should not move this models outside of your ui-project. Of course you can make a separate assembly with your models, or you can make one assembly per module, but you should never consume these models from your domain layer.
Write models - in my opinion - are not that specific to your UI. Instead they represent the data that is required by the command (e.g. SaveUserCommand). They can contain validation attributes, so your domain layer can validate them easily and they can be shared by domain layer and UI. In my project I have one class per command (e.g. SaveUserCommand, EditUserCommand, DeleteUserCommand) and related models (SaveUserModel, EditUserModel). Somebody will comment, that the they also contain some UI-specific code (e.g. the IClientValidateable itnerface for attributes or the attributes itself) and at least the IClientValidateable interface is a problem that I am willing to ignore to reduce the number of models. My experience with this approach (I also tried others) shows, that these models are very easy and it very easy to bind to these models.
Sometimes you will also have the problem, that you want to show some additional information in the edit-view. Instead of adding all this information to the viewbag, I will have another model, for example:
class UserEditModel
{
string Password;
}
UserEditViewModel
{
DateTime Modified;
UserEditModel Edit;
}
So my advice:
Create write-models that have all the data and validation logic that is specific to your use cases.
Create view models that contain all data you want to display and try not to use the ViewBag.
If you have a form, add the write-model to your view model. The write-model has all the data that will be sent back to your server via POST and then directly to your domain layer.
I use four "layers" in two assemblies
{application}.app assembly with three namespaces, just a regular class library project.
1) {application}.model for domain model
2) {application}.data for data using repository pattern
3) {application}.services for all business logic
{application}.WebUI assembly for the UI, this is the MVC project
Controllers only call services and services get and update data through the repositories.
There is an services API for every operation your app has to do, i.e.
OrderServices.Update (existingOrder)
OrderServices.Approve (existingOrder)
Services layer only know domain models, and controllers just assemble the viewmodels, using the domain models gotten from services, to send them to the views and prepare the domain models using the viewmodels gotten from the views to send them to the appropiate service.
This way you can eventually create an {application}.WebAPI or whatever that uses the same {application}.app assembly reusing all of the buissiness logic and keeping viwemodels where they belong (the WebUI project)
Hope this helps.
Best regards.
You could use a service architecture of your project , where all function and db queries are in this files and which you could using just by adding this code
IOrderService<Order> service = new OrderEntityService();
and use it like
service.Create(Order) or service.Update();
Whats strange to me is you're taking care and effort to layer out your app as much as possible, but you're still letting your MVC controller contain a lot of your logic. You're trying to share the objects and models, but the logic to add a new OrderEditViewModel is not shared, its stuck within that controller.
What I try and do is create a "helper" or "logic" class for each of my controllers. That logic or helper class is then injected into my controllers and wrapped in an interface. My controller can save, edit and remove items through my helper class, but has no knowledge of how its actually doing that.
I have then shared these logic classes along with the models to other projects, allowing a lot of code re-use. The problem is just ensuring that none of the "HTTP'ness" of the controllers sneaks into your logic classes, as these must be usable in a console or winforms application. So you have to be pretty strict and wrap a lot of things like HTTPSession or HTTPContext into interfaces that can then have non HTTP implementations..
Well, I understand your situation and also tends to a DDD (Domain Driven Design) solution as #MystereMan suggests.
I have an approach that sepparates the "Models" in 3 categories:
ViewModels: Have all the information necessary to display content data in the UI
RequestModels: Have all the information necesssary to send data, post/get/etc.)
AutoBindModels: Have all the information that is injected my MVC binding model (cookies, sessions, etc..)
And the most important, for all that classes I use as DTO/POCO's, actually they have no UI dependent code just properties/calculated properties and could be easily in any other project to be referenced by an UI project.
You could also create a Controller class that act as a Service outside ASP.MVC project and extend or inject it in your MVC controller.
Hope it helps...
I never reuse (Edit)ViewModels objects (this is not entirely true, I often share one EditViewModel between Create and Update but not always).
I design my ViewModels for specific Views. Therefore, I don't have to compromise my ViewModels when the UI changes (it changes all the time).
I take this as far as creating two distinct ViewModels even if they are identical. I'm done refactoring shared ViewModels..
I would answer yes to your question.
Hope it helps.
OrderEditViewModel and OrderViewModel are both 'ViewModels' end of the day. IMO, they may stay together in the same project even in your same 'ViewModels' folder. You may though create a sub folder under ViewModels for your 'EditViewModels'.
Now as you want to clean/tidy up the controller actions, you may want to use AutoMapper or ValueInjecter. You are mapping domain entity and view models manually. That is a tiresome job. With AutoMapper you can do something like:
var customerInfo = Mapper.Map<CustomerViewModel, CustomerInfo>(customerViewModel);

Developing ASP.NET MVC web applications the right way

I'm starting to develop a new ASP.NET MVC application, and I'd like to make sure that my understanding about the way of developing applications under MVC pattern is correct.
Question 1: Suppose that I have some main views (MainView1, MainView2, ...) with some partial views in it (PartialView1, PartialView2, PartialView3, ...). From what I have understood about MVC, I should define a Model for each view. e.g. I have to define PartialModel, PartialModel2, ... and also define my main models which are containers of the partial models which have been used in them:
public class MainModel1
{
public PartialModel1 Partial1 {get;set}
public PartialModel2 Partial2 {get;set}
public PartialModel3 Partial3 {get;set}
}
This way when I want to redirect to MainView, I can initialize the models used in that view by using this Model. Is my understanding of MVC correct? Or should communication between Views and Models be in another form in MVC?
Question 2: If the above is correct, Then suppose I have a partial view in some of my main view pages. This partial view has a submit button which calls an action method. This action method should somehow return the main page's view with the right viewmodels for views. Is there any recommendation about how to get/set viewmodels of other views in a partial view's action?
Thanks.
You understanding is correct. Each view (no matter whether it is main or partial) should have a corresponding view model (unless in the very rare case where this view contains only static html of course). And following this logic a main view that has to render other partial views will have a view model which itself will have reference (maybe as properties) to view models that are required by those partial views.
There is another technique which is using the Html.Action helper. In this case the partial is rendered through another controller/action than the main one. So you don't need to reference the partial view model in the main view model. They will be completely distinct. Take a look at the following blog post to learn more about Html.Action.
Your understanding is perfectly fine. This is what you can also refer to ViewModel in Asp.net MVC.
So, What basically is an Asp.net MVC ViewModel ?
In ASP.NET MVC, ViewModels allow you to shape multiple entities from one or more data models or sources into a single object, optimized for consumption and rendering by the view. The below image illustrates the concept of a ViewModel:
The purpose of a ViewModel is for the view to have a single object to render, alleviating the need for UI logic code in the view that would otherwise be necessary. This means the only responsibility, or concern, of the view is to render that single ViewModel object, aiding in a cleaner separation of concerns (SoC). Concerns are distinct aspects of the application that have a particular purpose (i.e., concern), and keeping these aspects apart means your application is more organized, and the code more focused. Putting data manipulation code in its own location away from the view and controller, enforces SoC.
Using ViewModels in MVC for finer granularity and better SoC leads to more easily maintainable and testable code. Remember, unit testing is about testing small units.
Along with better coding practices, there are many business reasons demonstrating why you might consider using ViewModels:
Incorporating dropdown lists of lookup data into a related entity
Master-detail records view
Pagination: combining actual data and paging information
Components like a shopping cart or user profile widget
Dashboards, with multiple sources of disparate data
Reports, often with aggregate data

ASP.NET MVC: having one model for all views

I like the way model binding in django works: you send stuff that you need in a Json-like way:
'param1': val,
'param2': val
In ASP.NET MVC you can't do it primarily because C# is a static language. You can use ViewData but it's ugly and not recommended.
So I had to create dozens of ViewModels for every view: IndexViewModel, AboutViewModel, etc. And today I got an idea: why not just create one Model class and have Visual Studio generate all necessary fields? It's almost like in django.
return View(new Model
{
Param1 = "asd",
Param2 = "sdf"
});
Param1 & Param2 are not members of the Model class, but Visual Studio will automatically generate them.
Now my question is, is it gonna work? The thing is that there will be a lot of fields in this Model class. And when we pass it to a view, only a small percentage of fields made for that view in particular will be used. Is it gonna be bad performance wise?
Thanks
If you have all these properties on your ViewModel which aren't used (i.e null or whatever) it isn't really going to impact performance. What it will impact however, is your design.
Generally speaking, one model to rule them all as you are proposing is a bit evil and goes against separation of concerns. ViewModel's should be very simple and should be tailored to the view. ViewModel's shouldn't really provide the view with more or less data than what the view needs in order to render.
Consider this....
You have a generic model with 15 properties on it and you only set a handful of them. Somebody else designs a new view and looks at the model, they may not know which of those properties are sent and under what conditions they are set. Consequently they may be attempting to display data that does not exist. This isn't a very clean approach.
I would stick to individual view models and where there is common functionality between views, create an abstraction or base ViewModel from which other view models can extend.
Edit: One other thing you could do is use the new MVC 3 (still in preview) syntax (dynamic) for setting ViewData properties directly as if they were properties.
So rather than doing
ViewData["FirstName"] = "Bob";
You can do
ViewModel.FirstName = "Bob";
This gives you dynamic variables automatically in MVC 3.
Have a look a Clay the 'malleable' object model being used by the Orchard Project.
http://weblogs.asp.net/bleroy/archive/2010/08/16/clay-malleable-c-dynamic-objects-part-1-why-we-need-it.aspx
http://weblogs.asp.net/bleroy/archive/2010/08/18/clay-malleable-c-dynamic-objects-part-2.aspx
There's no reason it shouldn't work.
You can even skip the Model class and create an anonymous type with just the members you need.
return View(new { Amount = 108, Message = "Hello" });
The problem using anonymous types is that you're giving up on auto-completion in the view since you won't be able to type the view according to the model.
Just use dynamic

What to put in your ViewModel

And what do you put in your View?
A recent blog from Scott Hanselman about using a special model binder for easier testing led me to think about the following:
What do you put in your controller logic building the view model, and what should be put in the view? what he does is this:
var viewModel = new DinnerFormViewModel {
Dinner = dinner,
Countries = new SelectList(PhoneValidator.Countries, dinner.Country)
};
return View(viewModel);
Now, I use the same way of passing data to my view, but I am unsure about how he deals with the Countries property. You could argue both sides:
Wrapping the Countries list in the SelectList prepares the data for the view, much like you create a viewmodel DTO to pass your data.
On the other hand, it somehow feels like you're specifically manipulating the data to be used in a dropdown list, limiting the way the view deals with your data from the controller.
I feel this is a bit of a gray area on the separation of concerns between the view and the controller, and I can't really decide which way to go. Are there any best practices for this?
PS: To keep it simple, let's assume the default ASP.NET MVC context, so basically your out of the box project. Default view engine and all that jazz.
In MVC (at least this flavor of it), one of the controller's responsibilities is to prepare the data for the view. So I think it is perfectly acceptable to prepare a specific model for the views consumption that implies it will be used in a drop-down. In this case the controller is just making it easier for the view and in fact prevents awkward code from having to otherwise be trickling into the view. It also keeps one from having those magic strings in the ViewData like VieData["Countries"].
So to sum up, while it may seem that there is some gray area in terms of responsibilities, ultimately that is the job of the controller: to interact with the view and to transform the domain model into other models that are easier to consume by the view.
Some suggest that having one all-encompassing view model per view is ideal (dubbed Thunderdome Principle).

ModelFactory in ASP.NET MVC to solve 'RenderPartial' issue

The 'RenderPartial()' method in ASP.NET MVC offeres a very low level of functionality. It does not provide, nor attempt to provide a true 'sub-controller' model *.
I have an increasing number of controls being rendered via 'RenderPartial()'. They fall into 3 main categories :
1) Controls that are direct
descendants of a specific page that
use that page's model
2) Controls that are direct
descendants of a specific page that
use that page's model with an
additional key of some type.
Think implementation of
'DataRepeater'.
3) Controls that represent unrelated
functionality to the page they appear
on. This could be anything from a
banner rotator, to a feedback form,
store locator, mailing list signup.
The key point being it doesn't care
what page it is put on.
Because of the way the ViewData model works there only exists one model object per request - thats to say anything the subcontrols need must be present in the page model.
Ultimately the MVC team will hopefully come out with a true 'subcontroller' model, but until then I'm just adding anything to the main page model that the child controls also need.
In the case of (3) above this means my model for 'ProductModel' may have to contain a field for 'MailingListSignup' model. Obviously that is not ideal, but i've accepted this at the best compromise with the current framework - and least likely to 'close any doors' to a future subcontroller model.
The controller should be responsible for getting the data for a model because the model should really just be a dumb data structure that doesn't know where it gets its data from. But I don't want the controller to have to create the model in several different places.
What I have begun doing is creating a factory to create me the model. This factory is called by the controller (the model doesn't know about the factory).
public static class JoinMailingListModelFactory {
public static JoinMailingListModel CreateJoinMailingListModel() {
return new JoinMailingListModel()
{
MailingLists = MailingListCache.GetPartnerMailingLists();
};
}
}
So my actual question is how are other people with this same issue actually creating the models. What is going to be the best approach for future compatibility with new MVC features?
NB: There are issues with RenderAction() that I won't go into here - not least that its only in MVCContrib and not going to be in the RTM version of ASP.NET-MVC. Other issues caused sufficent problems that I elected not to use it. So lets pretend for now that only RenderPartial() exists - or at least that thats what I've decided to use.
Instead of adding things like MailingListSignup as a property of your ProductModel, encapsulate both at the same level in a class like ProductViewModel that looks like:
public class ProductViewModel() {
public ProductModel productModel;
public MailingListSignup signup;
}
Then get your View to be strongly-typed to the ProductViewModel class. You can access the ProductModel by calling Model.productModel, and you can access the signup class using Model.signup.
This is a loose interpretation of Fowler's 'Presentation Model' (http://martinfowler.com/eaaDev/PresentationModel.html), but I've seen it used by some Microsoft devs, such as Rob Conery and Stephen Walther.
One approach I've seen for this scenario is to use an action-filter to populate the data for the partial view - i.e. subclass ActionFilterAttribute. In the OnActionExecuting, add the data into the ViewData. Then you just have to decorate the different actions that use that partial view with the filter.
There's a RenderPartial overload I use that let's you specify a new ViewData and Model:
RenderPartial code
If you look at the previous link of the MVC source code, as well as the following (look for RenderPartialInternal method):
RenderPartialInternal code
you can see that if basically copies the viewdata you pass creating a new Dictionary and sets the Model to be used in the control. So the page can have a Model, but then pass a different Model to the sub-control.
If the sub-controls aren't referred directly from the main View Model, you could do the trick Marc Gravell mentions to add your custom logic.
One method I tried was to use a strongly typed partial view with an interface. In most situations an agregated ViewModel is the better way, but I still want to share this.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IMailingListSignup>" %>
The Viewmodel implements the interface
public class ProductViewModel:IMailingListSignup
Thats not perfect at all but solves some issues: You can still easily map properties from your route to the model. I am not shure if you can have a route parameter map to the properties of MailingListSignup otherwise.
You still have the problem of filling the Model. If its not to late I prefer to do it in OnActionExecuted. I dont see how you can fill a Model in OnActionExecuting.

Resources