View Models in ASP.NET MVC

Being more serious, this is an interesting topic that the advisors and p&p team discussed a few times while they were building the Reference Implementation for the soon-to-be-complete Web Client Guidance, and it is something I've heard discussed time and time again out in the field.

I usually describe the "M" in both MVC and MVP as "the rest of the application", i.e. the business logic and business entities, and implicitly everything below in the stack. Some people don't like this analogy, saying the "M" refers only to the classes used to pass data between Controller and View. I agree it is arguably inaccurate, but I find it a useful way to think about a design based on these patterns... not least because of some of the variations in design I've seen that reflect those described below.

Where discussion gets interesting is when people start asking what the View can depend upon (and for the rest of this post think MVC, not MVP). To dodge a lot of detail this comes down to the following options;

1.Business Entities are passed to a View as the "Model". Therefore the View has detailed knowledge of part of the business layer.

2.Business Entities are never passed to a View – instead the relevant data is extracted and placed in a new entity reserved purely for use by the UI layer... or a "View Model" as people call it today (back when I coded as a day job we called these UI Entities so don't go thinking this is something new!)

These options become particularly interesting when you consider that in many modern systems the Business Entities are actually basically Data Transfer Objects generated or consumed by a tool such as the Entity Framework, nHibernate, etc, etc. This is useful because they may have validation behaviour built in. Business Logic is usually implemented as POCOs that manipulate, create, or return these DTOs.

This means that in option 1 the UI has access to all the validation goodness that exists on these entities. What's more, you don't need to create a new set of View Models that almost exactly match your data layer, and a set of "mappers" that convert Business Entities into a View Model.

However... note that I said "... almost exactly match...". You see, in the vast majority of systems there is something other than just what is stored in your database that needs passing to the view. This could be the current user's login name, or the current date and time. Or perhaps we must pass Boolean flags to indicate whether or not various regions of the screen should be displayed based on the user's roles.

To illustrate the differences, let's see 3 different examples as to how you might pass model data to a view. I've blatantly plagiarised some of the great comments that Francis, Julian, and the advisors made here so don't credit me with all the hard work J

Variant 1: No View Model

In Variant 1 we have no View Model at all, so our controller simply retrieves data from the business logic as a business entity, and passes it to the view...

publicclassModelController : Controller

{

publicActionResult Index(int someparameter)

{

BusinessEntity model = BusinessLogic.GetModel(someparameter);

return View(model);

}

}

The code for this is simple, concise, and requires very little work on my part. However, what if I want to add a property to indicate whether or not the "login" region of the view should be rendered? What if the view needs some other model data? This approach very tightly couples not only the business logic to the UI, but potentially the database to the UI (depending on your ORM tool, and how your business entities are created).

To summarise;

1.(con) This approach is unlikely to suit real MVC applications, as there is usually additional data that must be passed across.

2.(con) It is not flexible – it is more likely to lead to additional code churn after go-live other than in the simplest of cases.

3.(con) Developers that don't know these patterns well may consider adding UI-focused fields to your business entity, which compromises your business layer.

4.(pro) MVC can take advantage of the same validation mark-up attributes (or other scheme) that your business layer uses.

5.You can use it, but be prepared to take the hit for changes later, and make sure your developers know how to evolve it into Variants 2 or 3.

The bottom line is that I would use this if I knew it was very unlikely that the view (perhaps a very focused partial view in a very simple system) would ever need more than a single business entity... but other people, including the p&p guys, rightly have strong concerns about this approach.

Variant 2: Container View Model

In Variant 1 we saw how little code was needed for the simple case, but there are warnings about the inflexibility and risk to the integrity of the business layer. Variant 2 aims to maximise the benefits of Variant 1, whilst minimising the code you must hand-crank by using a simple View Model container to pass multiple business entities (and potentially other types) to the view...

publicclassModelController : Controller

{

publicActionResult Index(int someparameter)

{

BusinessEntity model =

BusinessLogic.GetModel(someparameter);

OtherBusinessEntity othermodel =

BusinessLogic.GetOtherModel(someparameter, model);

ViewModelContainer container = newViewModelContainer

{

ShowLogin = !User.Identity.IsAuthenticated,

LoggedInName = User.Identity.Name ?? "",

TheEntity = model,

AnotherEntity = othermodel

};

return View(container);

}

}

publicclassViewModelContainer

{

publicbool ShowLogin { get; set; }

publicstring LoggedInName { get; set; }

publicBusinessEntity TheEntity { get; set; }

publicOtherBusinessEntity AnotherEntity { get; set; }

}

Here we have the "ViewModelContainer" class, that is designed to carry our payload of a couple of business entities and some other primitives. Our Controller is responsible for fetching the business entities and then assembling this container, before passing it to the view.

So let's think about our pro's and con's;

1.(pro) Any data not contained in our business entities can easily be passed across.

2.(pro) Change is easy to handle when it consists of additive data.

3.(pro) Developers will most likely add UI fields to the View Model container, not to the business entity.

4.(pro) MVC can take advantage of the same validation mark-up attributes (or other scheme) that your business layer uses.

5.(con) But... your business entities must still match the precise requirements of your view. If you want to convert or translate internal system concepts into something easier to display, this is difficult using this model.

Overall, this is my personal favourite as it provides flexibility and future proofing for little extra effort over and above Variant 1. However, it is by no means perfect and you must be willing to consider replacing your business entities with custom View Model entities if the needs of UI and business layer diverge... i.e. convert to Variant 3.

Variant 3: View Model and Mappers

Variant 3 is what could be called the utopia practice, in that it ensures your business and UI layers are suitably separated, with "mapper" classes (often referred to as the "Entity Translation" pattern) marshalling the relationship between the two. However, it comes at a price – and that is a little coding effort.

Let's see how this looks;

publicclassModelController : Controller

{

publicActionResult Index(int someparameter)

{

BusinessEntity entity = BusinessLogic.GetModel(someparameter);

MyEntityViewModel model =

MyEntityViewModelMapper.ConvertFromBusinessEntity(entity);

return View(model);

}

}

publicclassMyEntityViewModel

{

publicbool ShowLogin { get; set; }

publicstring LoggedInName { get; set; }

publicstring Name { get; set; }

publicbool IsOver18 { get; set; }

}

publicclassBusinessEntity

{

publicstring Name { get; set; }

publicint Age{ get; set; }

}

This time I've showed the BusinessEntity class too so that you can see how it differs from the View Model. We can see that the Controller fetches this entity and then uses a mapper class to convert it to the View Model class. This mapper might also access environmental variables (e.g. User.Identity) or I might pass in other data.

The point with this approach is that the business entities are never passed to the view - only View Model classes can be consumed by views. This leads us to some findings;

1.(pro) Any data not contained in our business entities can easily be passed across.

2.(pro) Change is easy to handle when it consists of data that should be added, removed (or not displayed), or even altered / mapped (such as our Age field).

3.(pro) Developers will add UI fields to the View Model, not to the business entity.

4.(pro) The UI's needs are kept distinct from that of the business logic.

5.(con) But... MVC cannot take advantage of the same validation mark-up attributes (or other scheme) that your business layer uses. Instead you must duplicate this.

Conclusion

The great news is that the p&p Web Client Guidance Reference Implementation includes some great examples of Variant 3. Check out the SongDetailsViewModel, and the Mapper classes. It quickly becomes clear how much freedom this separation of concerns gives us, and how easy to follow the pattern becomes when you use it as a convention.

Hopefully the Variants above help you understand why this approach was chosen, and help you pick an approach yourself. Make sure you check out the Reference Implementation to see how this can work in practice.

Very well put! I like how you explain this as an evolving process when you start with a simple view. I’d only suggest variant 1 if and only if the whole team is willing to make the jump to the other variants when needed. Updating the business entities because of your UI is too big a risk if this is not an identified risk.

I don’t agree at all about DTOs and POCOs, its behavioral domain models that predominate most of the discussion you’ll find.

One other point I’d make, if you go for option 3 you have a definition of how to map from the domain model to the view model. If you can then access metadata that describes what rules to apply to particular properties on the domain AND if you have tool like PostSharp then you have the option to copy/map the rules from the domain onto the view model as part of the build.

Its tricksy code, and gets very hard when the rules are attributes, but it is basically possible and I can provide a code sample showing it if it is useful.

I agree that a lot of discussion is out there about domain models, but I don’t think that is a true reflection of how most people write systems… but rather it’s a smaller minority that happen to be vocal. I’m more than happy to be wrong here though as I don’t think one or the other is a clear winner; it depends on the scenario.

Also, I completely agree about copying rules to View Models – I had this tooling approach in the back of my mind when I wrote the text above but I guess that isn’t clear. If you do blog any code about how you’ve done that I’d love to see a link so feel free to post here 🙂

Vocal, yes. They’re also the small group thats influenced key technologies including ASP.NET MVC and EF. It does depend on your scenario, but I think too many people make uninformed decisions based just on what the latest Microsoft tooling offers, and I don’t think thats the way modern systems should be developed.

Most people who use domain models also realize that they aren’t always the best option, but many people who use DTO based business logic don’t seem to know enough about the alternatives for my liking.

I can definitely put together some of the code and e-mail it to you, it definitely seemed a workable option but it’d need further development. In particular it worked for code-based rules and for attributes with no arguments. Anyway I’ll send you something in the next week or two if you’re interested.

I’d love to see a blog post on how you’ve done that! It’s easy to digest that way, and time is money, as they say!

Hi Craig,

1) I agree, but fundamentally that is still mapping… just using a funky technology. It also depends on the rest of your architecture – your View Model and EF context might be many layers apart!

2) That’s a very interesting comment… it "feels right" to me, but then the more I think about it I’m not so sure… you see if I can possibly push any validation up from the database or business layer all the way to the browser client (and repeat it server side of course!) then I will. That means that if the field is displayed on the screen and it has validation, I want to "push it up the architecture stack".

What I think you’re probably referring to is what I meant by;

"…your business entities must still match the precise requirements of your view…"

… when I was discussing Variant 2. If the EF entity doesn’t match your needs for the UI, you should probably be using Variant 3. Does that make sense?

Well, I’m of the opinion that one should nearly always use "Variant 3" anyway.

Regarding #2, consider the following. Imagine a system which collects timecards for employees. Employees are permitted to fill in a start time and a stop time, in which case the system will calculate elapsed time for them, or to fill in and elapsed time without a start time and a stop time. Timecards are represented at the Entity Framework by the type TimecardEntity, and at the UI level by the type TimecardPresentation.

At the TimecardEntity level, it certainly makes sense to have the ElapsedTime property be required. Whether or not the user fills it in directly, it must be present before the entity can be persisted to the database. On the other hand, StartTime and StopTime are not required.

The user interface’s validation rules are different. The user must fill in either StartTime and StopTime (in which case, any value for ElapsedTime would be ignored and replaced with a calculated value by the system) or just the ElapsedTime. So it does not make sense to make ElapsedTime required, but it does make sense to validate that either ElapsedTime or both StartTime on TimecardPresentation are filled in.

Validations, of course, are not the only thing which can vary. Other attributes you might put on your presentation model, like Description could be different if the same Entity Framework data might be displayed on two different user interfaces, via two different presentation models.

I would add a radical view on this topic. Lets consider Variant 4 – "No Domain Model". Or in other words "Only View Model".

(pro) – maintain only one domain model (the model defined in the database). No need to maintain artificial abstraction layer of classes having exactly the same structure as the tables in the database.

(pro) – higher performance and scalability. We need to show a list with 3 columns – lets extract only the data for these columns and fill the appropriate view model objects with these 3 properties, instead of pulling all data for all 20 properties/fields in our domain model and show only 3 of them. Less data reads, less internal network usage, less memory usage, faster UI response time and better scalability.

Just to clarify – by "No Domain Model" I don’t mean direct database access in the UI with no abstraction between. What I mean is to model in the middleware objects suitable for the consumer layer (in this case the UI) instead of recreating the database model.

There are scenarios where the duplicated domain model is usefull (when an API has to be provided for integration with third party systems and the exact data usage is not specified – i.e. it is not possible to define view models in advance), but when considering a common web based application, its API is only by itself.

All good points; any system that has these kinds of complexities is a very strong contender for Variant 3, and that’s why the p&p guys went with that approach in their guidance.

Hi Nikolay,

you make an interesting point. I must admit I initially thought "what?!" but then I read through your comment again and I see what you’re saying.

I think it’s basically very similar to the age old discussion about whether or not data access classes should represent a database table or the needs of the UI. I forget the pattern names but this has been a huge discussion on and off in various forms.

To be honest I think modern ORM tools mean that you can do what you describe using a framework like nHibernate or the EF, mapping just the database fields you need for the UI, and then use Variant 2 of my approaches above… this gives a very close approximation of what you describe. I also probably wouldn’t recommend this for performance reasons; in reality most "average" systems have much bigger and more serious bottlenecks, and a well structured, clearly coded system is far more likely to be maintainable, and IMHO to perform well.

Most of the O/R mapping frameworks support lazy loading, but its efficiency compared to explicit and selective data loading is another story.

It is clear that for many systems the performance and scalability are rarely the biggest problem. This is especially true for enterprise level solutions usually accessed by a small number of internal users.

As you said the maintainability is one of the most important aspects and in such cases it is usually priority #1.

The number of view model entities is much higher than the number of domain model entities, so if one wants less maintenance overhead, probably the best balance is provided by the hybrid solution (Variant 2: Container View Model) – no need to create and maintain explicit view models, but still having the ability to add view specific information without breaking the domain model integrity.

This is a really nice walk through the ways to get a model up to the view. I tried Variant 2 for a while, thinking views composed of business entities plus anything extra was the best way to go. But I had properties and methods in my business entities I really didn’t want the view going near.

They really are separate concerns. They may overlap a lot, but they ultimately serve different purposes.

So I’m all about Variant 3 these days with AutoMapper to make the conversions easier. I also think one view model per view will become more valuable with the new html helpers in MVC2 that spit out your entire view model for display/edit.

It does seem like the last mile on Variant 3 is getting centralized validation rules from the business domain up to the view model so your controller can take advantage of the model binder validating for you.

I’m just decorating my view models with the Data Annotations attributes and living with that for now.

I also would like to thank you for this article; it is well structured and very helpful. Now I have kind of a dictionary of the modelling options, so even the the conversation inside my head is much easier when thinking on the topic.

There is something that could be added as a pro for variants 2 and 3 (having view models): no security concerns regarding automatic model binding – when a view model is used there is no chance for the hacker to update data in fields not supposed to be updated (role, user rights etc.). The exclusion from binding works, but what happens when somebody adds properties to the entities in the domain model and forgets to go and add some or all of them to the list of excluded properties for binding.

It is not about pros and cons of ORM’s and how efficient they are, but about view vs domain model.

In your example the code fills a view model with data from the domain model. If it was not using an OR mapper, the domain model would not be really needed as the knowledge about it would be capsulated in the stored procedure or the adhoc SQL query.

One more thing to add on the view model vs. domain model. The validation rules specified in the domain model are general and assume full object validation, so no rules like "if this is a new customer, we want only to have his/her email and password, but if he is updating his own profile the first and last name are mandatory".

The partial data entry interfaces (wizards) also have a problem with this full validation specified on domain model level – step one of the wizard asks for some of the data and it has to be validated before going to step two, but the domain model validations could consider the object invalid at the first step as other required fields are empty (they are supposed to be supplied at step 4 for example).

Maybe some kind of a validation category (ApplyOnCreate, ApplyOnUpdate, ApplyOnStep1 etc.) could be added to the data annotations and implemented in the custom validation methods to solve this problem.

Another issue with the domain models is easily visible with the simple user registration/creation scenario – enter a password and repeat the password. Is the repeated password part of the domain model – no, but how to deal with it from modelling perspective.

Good post. I think there is a forth (or I should say fifth) variation: (a variation of) CQRS.

So if we were to take your third variation one step further, we would get View Model directly from whatever the controller is calling into (it being BusinessLogic class or application service or database through an ORM!!). That way you can share your validation logic on the server and client, because you are basically using the same class and your class is very view specific so it shares all the pros with your third variation.

It also has some other added benefits; for example,

there is no mapping whatsoever. View Models are stored in database as tables; so your view model is a OO representation of your table (or actually it is the other way around: your table is a database representation of your view model :o))

But is it not what Nikolay explained above? To some extent except that Nikolay thinks there should not be a domain model: only VM is required. I believe domain model is required, because VM is like a DTO with some little (mostly validation) logic, but where does all that complicated business logic go? It goes into the domain model.

In my opinion the business logic has to be placed in its own domain, otherwise we add to much dependencies.

If we have an entity "Seller" and there is a business logic doing a check for VAT number validity through an external service, sending email notifications to account managers for newly registered seller etc., do we place this business logic in the domain objects and make them dependant on the VAT service objects and email notification objects?

I would prefer to have only internal dependencies inside the domain model and place the orchestration in explicit business logic objects using the domain model, the external services etc.

The reality is that most of the domain objects are more or less pure DTO’s serving as a memory storage for the data comming from the RDBMS with some validation added and as such I don’t like their presence if I have to build another layer of abstraction on top of them so it can serve the views in the application.

I dont like them, but I usually have a domain model in the middleware as there are too many simple use cases (probably 80% of entities), where the domain model entities can be directly used as view model entities and there is no need to add and maintain additional level of abstraction (view models). However, as all definitions are abstract, we could say that the domain model entities in such cases are actually view models as they perfectly serve the application views.

Don’t get me wrong, I am defending the "view model only" approach only to get more feedback on this concept. The reality is that every architecture depends on the requirements and the project constraints.

Building a small system for intranet usage could be done in many ways (less concerns on performance/scalability, more on maintainability and time to develop/price), while building an application accessed by a large number of users over internet requires a different approach (more careful approach to memory consumption, efficient data access and modification patterns, caching etc.).

I agree with almost everything you said; there are just a few minor things as follows:

– Domain Models are not DTOs unless you are using anemic domain model in which case you do not really have domain model. This is how Microsoft promoted the use of EF1.

– I would not put validation on my domain model except for invariants. Validation is to be done on the user input based on the context. So validation on the "same data" on one context could be different on a different context.

I completely agree Variant 3 requires additional effort, although I think you’re quoting a worst case… but this is always a game of balancing trade-offs. I guess this post is intended to help people make the decision as to which is right for them. I’m not a believer in there being one correct approach.

The popularity of automapper is interesting too… thanks for the comments!

Just did a quick test with two classes having 10 properties each – for 1M objects the handwritten data copy took 166ms, while the automapper needed 21268ms. This is a difference of 128 times (not percentages).

Would it be a bottleneck – no, at least in an average application, but the maintainability aspect is also not black & white.

The automapper would handle newly added properties to both classes (if they have the same names), but if one changes a property name only in the source or the target the automapper would be unaware of the change and there will be data lost, while a handwritten mapping source code would mean either a compiler error or automatically renamed field in the mapping code using the refactoring tools in VS.

technically, yes… but if you’re aiming for Variant 3 the problem with your approach is that you don’t have a separate model for each View. Instead, I’d probably create a base abstract ViewModel class and inherit from it if I needed to reuse properties.

Otherwise change might affect multiple screens, as developers will add UI fields to the generic View Model. All the Views’ needs become entangled which would concern me.

Yeah, I agree, what is was driving at was not using base classes for your entities. In a more real world scenario you’d defiantly need to be more careful about what goes into a base view model container.

This thread has been dormant for several months – but it contains the best list of options, and it has one radical proposal already; so I'll throw one of my own… In vast majority of cases I don't see a reason for View Model; basing a view on domain model is just fine.

Let me qualify a few things… First, I am talking specifically about "input" views (Edit or Create) – not about Display views (List or Details). Second, there are exceptions (timesheet may be a good example) – where View Model is significantly different from domain model – in my experience this amounts for 20 per cent of cases at most. Third, if in the future ASP.NET MVC will have something like UpdateModel(DomainModel m, ViewModel vm) that will automagically update matching fields – I will be happy to rethink this radical statement. AutoMapper is probably a step in that direction.

@Simon, you advocate Variant 2 which is essentially a "union" of two business entities and some unrelated data. In your example it's login information that is usually orthogonal to the view, and is better presented in partial control. The example of two business (domain) entities that I can think of is Order Header (read-only on the page) and Order Details (Input). Again, having Order Details – maybe through RednerPartial() – based on domain model seems easier to develop and to maintain. So, Variant 2 becomes Variant 1 all by itself.

The obvious two benefits are that you can leverage DataAnnotations from the model – both in display and validation. The downside… again – my experience that in 80 percent of the cases ("edit customer" or "create new order") there seems to be no downside.

For the record, I've done MVC programming in PHP for about 5 years now; and I am managing an ASP.NET MVC project for the last year. I've read a lot of posts (including from people whose opinion I take as gospel) that advocate Variant 3 ("always use View Models") – so it took me a lot of thinking to come to this heretical conclusion…

This article just made MVC click for me. I've been tinkering around with it for a while and just failed to fully realize how to make the webforms side of my brain "get it". This article, and specifically variant 3 just made that happen!

I think you're entitled to that preference, as long as you're explicitly making that choice. I'd just say "if you need to move up to variant 2 or 3, do so rather than hacking your domain entities". If you're happy with your team all following that guidance, fair enough!

I still believe in variant 2 as the starting point, moving to variant 3 if needed. I find it's the best balance of risk traded against development effort.

I'd normally expect the menu to be encapsulated in a Partial View of some description, so you'd just have a single MenuViewModel that is paired with that View (I usually recommend each ViewModel class is "owned" by one View, with some exceptions). Therefore, I don't see a problem here?

As for mapping methods, if doing it the manual way I would create a class per source or destination type, depending upon your preference… although I'd prefer an automated solution like AutoMapper.

I think reuse is actually better in MVC, it just takes a bit of getting your head around, so I understand your pain. Perhaps I'll blog on that sometime.

@Simonince: Good articles, man. I approached same with Variant 2 and a little bit with Variant 3. I have built ViewModelContainer and using AutoMapper for mapping between my DTOs from WCF service to ViewModel.

I totally agree… although that of course may have a tiny perf impact. Nothing comes for free, but I personally love AutoMapper. I have worked with teams that love it and teams that would rather hand-crank the code though… so I'm not too prescriptive.

The great news is that the p&p Web Client Guidance Reference Implementation includes some great examples of Variant 3. Check out the SongDetailsViewModel, and the Mapper classes. It quickly becomes clear how much freedom this separation of concerns gives us, and how easy to follow the pattern becomes when you use it as a convention.