Flattened and derived properties with Automapper - asp.net-mvc

I'm working on an ASP.NET MVC site, using EF4 and Automapper. I'm making good progress, and feel fairly good for the design (considering this is my first stab at a true DDD architecture). But I'm starting to see some things that I'm not too comfortable with.
The questions I have probably relate more to my lack of experience with Automapper and DDD, so they may be fairly easy for some of you to answer and point me in the right direction. There's also a very good chance I'm going about this completely wrong, but my direction is based on what I'm reading on here, some from searching, and some from asking my own questions. But I'm also starting to realize that some of the "advice" I'm seeing is contradictory to each other.
Quick background, my domain model is simply the generated POCOs from EF4 POCO template (anemic). These are used in my service layer, and they are also exposed to my application via the service layer. I don't have any sort of DTO, just my anemic domain model, view models, and Automapper to map the two, per the advice I was given. This is all fine and dandy assuming they can be mapped one-to-one.
My problems come in when I have to flatten my domain models into one view model, or when I need some business logic to define a view model property.
Two examples:
Flattening
I have two models, User and UserProfile. This is a one-to-one mapping, so it already is logically flat -- it's just in two separate models. My view model needs properties of both User and UserProfile in one object. From what I've seen, Automapper has no easy way to do this, so what I did was extend my User POCO, adding the needed UserProfile properties to it:
public string UserName
{
get { return UserProfile.UserName; }
}
I'm not a big fan of this as it seems to violate DRY, and may become a bit of a pain the more I have to do this.
Encapsulating business logic
I have another case where a User property isn't stored, but rather derived, and needs to do some logic before returning a value. For example, a profile image URL will depend on whether they registered with Facebook or Twitter. So I have something like this:
public string ProfileImageUrl
{
get
{
if (User.TwitterId != null)
{
// return Twitter profile image URL
}
if (User.FacebookId != null)
{
// return Facebook profile image URL
}
}
}
I'm pretty sure this isn't something that Automapper is responsible for, but I'm not sure if this should be done with a domain model extension if I want to keep it anemic. So I'm not sure where this belongs.
I'm not completely stuck on having my domain model be anemic (I know that's its own debate), but I do anticipate this domain model being used by multiple applications with different view models and validation.
Thank in advance.
UPDATE: In response to #jfar, my main issue with the flattening example is that it seems like this should be something Automapper should be able to do. If not, then I can live with this option. I was just looking for someone to double check my design to make sure there wasn't a better way to do this.
My issue with the encapsulating business logic example, is that I'm violating the anemia of my domain model. In some cases, this may even need to hit the repositories to pull certain data for business logic, and this seems like a bad design to me.
The other thing I'm starting to wonder, is if I shouldn't have a DTO layer, but I honestly don't want to go that route either (and per the question I linked above, it seems to be more accepted not to use DTOs w/ DDD).

Flattening: You can chain your mappings together using Automapper's ability to map to an existing object.
Chain Example
Encapsulatng Business Logic: I don't really see your problem. However, if you want Automapper to be responsible, take a look at before and after maps or custom resolvers. Custom Resolver Example

Why are you so intent on keeping your domain model anemic? It looks to me like your domain objects are nothing more than DTOs.
The ProfileImageUrl belongs on your domain class that has the necessary information to return the correct URL. I'd imagine this is UserProfile. If a single class doesn't have the needed information thats what a service is for. You either create a method on your service that returns the URL or a composite object like Darin Dimitrov suggested.
Firestrand and Darin Dimitrov's answers are both good ways to accomplish flattening.

Define a model that regroups those two models:
public class UserWithProfile
{
public User User { get; set; }
public UserProfile Profile { get; set; }
}
then have your service layer return this model. Another possibility if there is a 1-to-1 mapping between User and UserProfile is to define the following model:
public class UserWithProfile: User
{
public UserProfile Profile { get; set; }
}
Then define a view model containing only what is needed by the given view:
public class SomeUserViewModel
{
... only properties needed by the given view
}
next define a mapping between your model and your view model:
Mapper.CreateMap<UserWithProfile, SomeUserViewModel>()
...
and finally in your controller use the service layer to fetch the model, map it to a view model and pass this view model to the view for rendering, pretty standard stuff.

I searched and read about flattening more, and the more I searched, to more it looked like Automapper should be handling this automagically. After playing around a bit, I found a way to get this to work, though I still can't find any examples of doing this, even with Automapper's documentation.
The key is to name the property on the destination object with the fully qualified name of the source object graph.
Source objects:
class User
{
int Id { get; set; }
FacebookUser FacebookUser { get; set; }
}
class FacebookUser
{
string UserName { get; set; }
}
Destination objects:
class UserViewModel
{
int Id { get; set; }
string FacebookUserUserName { get; set; }
}
So:
UserViewModel.Id -> User.Id
UserViewModel.FacebookUserUserName -> User.FacebookUser.UserName
Maybe this should have been obvious to me, and maybe it is for most people. And now that I think about it, it makes sense -- it's really the only way it could work. I just didn't figure it out until now.

Related

ASP.NET MVC + Entity Framework - How to deal with DTO's and ViewModel's [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'll try to describe a problem that I see very often in my workplace, but I couldn't find a way or a reasonable solution to it. I searched a lot about this and all I could find is what I already have implemented. The scenario is this:
I have an ASP.NET MVC app using Entity Framework which follows the Repository Pattern. I will use a simple Student/Teacher database structure to exemplify
Entities
public class Student : BaseEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Teacher Tutor { get; set; }
}
public class Teacher : BaseEntity
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Student> Students { get; set; }
}
public class BaseEntity
{
public byte State { get; set; }
public Datetime CreateDate { get; set; }
public Datetime UpdateDate { get; set; }
}
Now, let's say I need to expose a method to return a list of student names along with its teacher's name:
var students = context.Students.Include(x => x.Teacher).ToList();
The query above is bad and we all know it, since it returns all columns. Now, if we refactor to this:
var students = context.Students.Include(x => x.Teacher)
.Select(x => new
{
Name = x.Name,
TeacherName = x.Teacher.Name
}).ToList();
I'll have a performant query that select only the fields I want. That's good. But now I need to make a choice. To return this list to my controller, I can either: Create a StudentDTO, or populate a Student instance with only the columns I selected in my query.
DTO approach
If I create a DTO and pass it along to my controller all will be "fine". No worries with extra unnecessary fields.
Return EF Entity Student
If I return the database entity to my controller as is, even though I loaded it with only the fields I wanted I will get all the other empty fields. So I create a ViewModel to return only the data I want. (This is what we are doing right now in most methods along with AutoMapper)
Problem:
See the pattern? Either way I will ended up creating a class to map my return. I'm fine with this most of the time, but in the project I'm working right now, we have several methods to expose and each of them has a different return structure. For example, what if I wanted to return a list of students that contains only student Id and Name? Create another DTO or ViewModel?
The project has a team of 5 developers and the ViewModel folder is getting pretty stuffed with classes. I started instructing them to return an anonymous object inside a controller when a method return is very specific. I only create View Models now when I'm sure it can be re-used elsewhere.
But this anonymous approach had become also bad because now I have to do this in several controllers and I feel I'm repeating myself.
Is there any other approach I can use to solve this? Of course the project I'm talking about is much more complex than this example, with several entities and pretty complex queries. I feel this happens a lot in other projects and I failed to find a decent way out of this.
I wish I would have stumbled upon this question a year ago. Hopefully this info helps you or someone else even though its been awhile.
You are exactly right. You see a problem and your gut is already telling you there is an architecture problem and you are right.
I know it is a pain but the DTO approach is the correct architecture in my opinion. These classes are a pain to create and use and we have all tried to shorcut around them at some point. But, you should be inheriting from base classes to share properties between objects to ease your pain. Also, use a 3rd party open source tool like automapper to move data easily between your data models and your dto objects.
Developers make this architectural mistake all the time (trying to bypass the DTO object) especially if they are working on smaller software systems and not large corporate enterprise systems where the above architecture will fail fast while it may succeed forever in a small system.
using your first example:
var students = context.Students.Include(x => x.Teacher).ToList();
You would then copy students into a dto object (perhaps StudentDTO) and then pass this up to your UX and translate it into a viewmodel object. If Student and StudentDTO are identical then they can inherit from the same base class and StudentDTO gets created with about one line of code.
Using your second example
var students = context.Students.Include(x => x.Teacher)
.Select(x => new
{
Name = x.Name,
TeacherName = x.Teacher.Name
}).ToList();
If you do not do this and instead translate everything into a ViewModel then you will end up with endless viewModels as you have.
However, even more importantly here, you shouldn't be able to move it into a viewmodel because ViewModels should sit in your UX layer and the fact that you can do this would indicate a small architecture issue on its own. ViewModels are only applicable to the UX and not anywhere else so keep them in the UX layer.
If you move your viewmodels into the UX you would find that you could not move your EF objects into your View Models and this would have steered you down the DTO architecture approach instead.
So why dont you just pass EF models up to the UX?
Well, you can. Works good in simple scenarios when you are just editing a single student for instance. This is tempting because its so easy to do and it works so why not do this?
For very simple, small systems please do. I think this is fine. you can pass an EF model up to the UX, translate it into a viewmodel and then the viewmodel back to the EF. To do this your EF models should sit outside your data and ux layers in their own layer. I typically use a dll called something like "MySoftwaremName.Common". I place all interfaces, data models and dtos in this layer and reference this layer from the UX, Service and Data layers so that DTOs and interfaces can easily be passed up and down the architecture.
My primary real world experience has shown that the primary reason you do not pass EF models directly up to the UX is Caching.
In small systems developers may not deal with this so this may work just fine. But in large systems where we are getting hit 50,000 to 100,000+ times a second caching is key.
What if you wanted to cache your student object so that it could be retrieved for the next 5 minutes without you hitting the db over and over again.
You cannot cache the EF models in ASP.NET or you will eventually encounter severe issues that are occuring randomly in your system that are hard to trace down.
You can stick the EF objects in Cache and even retrieve them from cache. However, EF entities are attached to Database Context objects and that context eventually goes out of scope and gets garbage collected by .NET. If you still have your Student object in cache after this happens and you retrieve it and try to use it (using your own example again) to get the Teacher subclass "Student.Teacher"
you will get the yellow screen of death if that Teacher object is not eager loaded and is lazy loaded By EF. Ef will try to use the context to go fetch that Teacher and there isn't one and it will blow up.
To prevent all this it is best to move your EF objects into DTOs and then you can safely tranfer this data, cache it etc without any worry.
The only pain in this architecture comes in translating DTOs to viewmodels and EF models exactly as you have stated. But as I mentioned above, using proper base classes to share fields and using something like AutoMapper or another Mapping engine will help you map quickly from DTOs to ViewModels and EF objects.
Always create a ViewModel. The ViewModel is a UI concern. your entity framework model is a domain concern. ViewModels aren't about re-use. They are about defining only what you need to satisfy the View that uses them.

What is the appropriate granularity in building a ViewModel?

I am working on a new project, and, after seeing some of the difficulties of previous projects that didn't provide enough separation of view from their models (specifically using MVC - the models and views began to bleed into each other a bit), I wanted to use MVVM.
I understand the basic concept, and I'm excited to start using it. However, one thing that escapes me a bit - what data should be contained in the ViewModel?
For example, if I am creating a ViewModel that will encompass two pieces of data so they can be edited in a form, do I capture it like this:
public PersonAddressViewModel {
public Person Person { get; set; }
public Address Address { get; set; }
}
or like this:
public PersonAddressViewModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public string StreetName { get; set; }
// ...etc
}
To me, the first feels more correct for what we're attempting to do. If we were doing more fine grain forms (maybe all we were capturing was FirstName, LastName, and StreetAddress) then it might make more sense to go down to that level. But, I feel like the first is correct since we're capturing ALL Person data in the form and ALL Address data. It seems like it doesn't make sense (and a lot of extra work) to split things apart like that.
Appreciate any insight.
If you are using all the fields of the Person object, then there's nothing wrong with using a complex view model. However, if you are only using a field here or there, then it's much better to build your viewmodel with only those values you are using.
You can do your view models any way you like, but the whole point of having them is that a view model should be customized to the view it's representing.
It can also be a lot easier to use the first method if you're using something like AutoMapper to map to business or domain models, because the objects should have similar definitions.
You're not using MVVM. You're defining ViewModels, classes for only view purposes in order to avoid to break the Model classes. In that case you can define the properties you want for your best profit. In the example I will go for the second solution but it's up to you.
I'm working on a big project with many developer providers. In that case the customer let us to define the ViewModels that we want keeping the Models (Business Entities as they call) for their concern. Because we are different groups no one is worried about another ViewModels so you can even use one class for one view, no matter if another view is different a little bit from the first one. That's one of the advantages of ViewModels instead of pure Model using.
I prefer to define the ViewModels in client-side through JSON objects for the sake of data binding. With this you can truly use MVVM through knockoutjs, angularjs, backbonejs, etc....
If you want to use MVVM check knockoutjs. It's very easy and pleasant to use
Using Model classes directly or wrapping them (as in your 1st example) in your ViewModel class can be a potential security issue if your Model classes have some sensitive properties (i.e. IsAdmin in the User class).
Say your controller actions takes a PersonAddressViewModel input parameter:
public ViewResult someAction(PersonAddressViewModel personAddress)
{
//save it
}
A malicious user can basically set any property in your PersonAddressViewModel composite object even if your UI does not provide such capabilitiy.
This is made possible by the default binding mechanism of the MVC.
To avoid this, either don't wrap sensitive model classes or use the Bind attribute
More on this here: Pro ASP.NET MVC 3 Framework 3rd Edition By Steven Sanderson , Adam Freeman (Chapter 17)
If you're using that view model to render a form, I would vote for the second approach, since you're combining all the view data required for the form.

Why does the interaction between model, view and contoller look different?

Im new to ASP.NET MVC, trying to learn the basics.
Im now trying to learn the relationship between the model ,view and controller.
The interaction between these three looks different, why? (Look at the arrows)
Source 1: MSDN
Source 2 (Page 65): Steven Sanderson
I would be glad if you help me sort out my confusion
Thanks
Edit:
What you are saying is that mvc can be implemented differently?
(Still asking about asp.net mvc - Not mvc in general)
I have been looking at the mvcmusicstore
and it looks like this.
Controller:
public ActionResult Details(int id)
{
var album = storeDB.Albums.Find(id);
return View(album);
}
Model:
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public int ArtistId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string AlbumArtUrl { get; set; }
public Genre Genre { get; set; }
public Artist Artist { get; set; }
}
view:
(Had to add as image, add code the normal way did not work)
This looks like the MSDN version, how would this be rewritten to fit Sandersons diagram?
Maybe this will help me understand!
Edit again:
Hi again
Let me sum this up. Please respond if I'm wrong.
The way Microsoft intended us to use mvc is the one we see in the above MSDN link and in MusicStore.
Then there are other "versions" of mvc such as Sandersons (or whereever it originates from).
So Microsoft give us a basic way of how to use the mvc framework, but it is ok to do it other ways.
A newbie should not get stressed by seeing different versions, sticking to the one seen in MSDN/MusicStore is perfectly fine.
The key difference is the inclusion of the "Presentation Model" in Sanderson's diagram. The ASP.NET MVC implementation often uses the Model as the Presentation Model, even though they can be different (and I would argue that they should be different, but it's a holy war and there's no need to get into that).
In most very simple ASP.NET MVC applications, the model is the data entity. Whether it's an EF entity or a Linq2Sql entity, makes no difference. This is because most applications are simple forms-over-data and the presentation is probably one-to-one with the persistence.
The MVC pattern itself, however, doesn't require this. In a more pure framework-agnostic form, Sanderson's diagram illustrates the fact that the controller is interacting with the model. The model is really the "gateway to the domain core" in this sense. Controllers and views are part of the application, but the model has the underlying business logic and, beneath that, layers of persistence and other infrastructure information (properly separated, of course) which are unknown to the application. The boundary between the controller and the model is the application boundary, the point at which other applications can also connect to the domain core and interact with it.
A presentation model is usually nothing more than a simple value object. It's not an entity of any kind in the sense that it doesn't have to exhibit any business behavior or maintain its lifecycle the way that a persistable business entity would. It's just a flat object with some attributes of data.
It can have some behavior, but that behavior is for the application and not for the domain core. For example, maybe it has some methods or properties that the view can use. The presentation model is part of the application, so it's presentation-layer-aware. Essentially it just holds data that the controller needs to pass to the view (or even receive from the request, depending on the framework).
In ASP.NET MVC you'll very often see the model used also as the presentation model. The same object may be playing two roles in those cases, but the two roles are definitely different.
Edit: Just noticed your updated question...
In that example, Album is playing the role of both domain model and presentation model. (In fact, I would argue that it's not a domain model at all because it's too anemic. Notice that it has no functionality, just bare data.) In a richer domain model, Album would likely have more functionality. For a contrived example, imagine that instead of auto-implemented properties it has properties which enforce business logic when set, and it has methods on it such as AddSong(Song song) and Play() and other such behaviors.
This richer model can still be used as a presentation model, but the functionality might not make sense in the scope of a view. A view is really suited more toward just bare data elements. The controller would interact with the model's functionality. So you might create a presentation model similar to the Album domain model in structure, and it would look just like the one in your example.
Going forward, what if the view needs other data as well? Maybe the view needs to know something about other models which aren't part of the same aggregate as Album. It wouldn't make sense to modify the domain models to accommodate the view. That's backwards. The presentation should wrap around the domain core, not the other way around. So you might add properties to the presentation model which are populated from other things inside the controller.
So you might end up with something like this...
Domain model:
public class Album
{
public int ID { get; private set; } // might need to be immutable
private string _title;
public string Title
{
get { return _title; }
set
{
// don't allow empty titles
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException("Title");
_title = value;
}
}
private Album() { }
public Album(int id, string title)
{
ID = id;
Title = title;
}
public void Play()
{
// some implementation
}
public void SomeOtherMethod()
{
// some implementation
}
}
As the business domain grows and changes, this model could change with it. The main point is that it changes at the behest of the domain core and the business logic, not at the behest of UI implementations.
A particular "page" on a particular website which uses this domain core may need specific information about an album, and maybe some other information as well. You'd tailor a presentation model to fit that:
public class AlbumViewModel
{
public int ID { get; set; }
public string Title { get; set; }
public string Owner { get; set; }
public IEnumerable<Listener> Listeners { get; set; }
public string SomeCompletelyUnrelatedValueNeededByTheView { get; set; }
}
The controller would then construct this presentation model for the view:
public ActionResult Details(int id)
{
// TODO: validate and sanitize any inputs
var album = AlbumRepository.Get(id); // after all, why bind the UI _directly_ to the DB? that's just silly
var someOtherObject = SomeOtherRepository.Get(someOtherValueFromSomewhereElse);
var albumVM = new AlbumViewModel
{
ID = album.ID,
Title = album.Title,
Owner = somethingElse.SomeValue,
Listeners = someOtherObject.GetListeners(album),
SomeCompletelyUnrelatedValueNeededByTheView = "foo"
};
return View(albumVM);
}
This is a much more manual approach overall. It's useful when you have more complex domain models, multiple complex applications interacting with that domain, different technology stacks throughout the domain, etc. For simple forms-over-data applications the standard ASP.NET MVC implementation usually works fine. Most of the tutorials for it reflect this, consolidating multiple responsibilities into fewer objects, using decorators instead of explicit code (assuming the use of the same stack of tools across the board), etc.
The examples you're looking at get you to a working application very quickly with very little code. As with any framework, it works beautifully if you do things the way the framework intends you to do them. If you need to step outside the bounds of the framework, you can still maintain the pattern in a more abstract and framework-agnostic way.
Edit: For your update again...
In a way, yes. ASP.NET MVC is a framework which borrows a lot from the MVC pattern in general. As with all things, there's more than one way to do it. Sticking with simple implementations and quick applications, the functionality provided by the ASP.NET MVC framework and explained in its various tutorials is perfectly acceptable and is a great example of the use of a framework... Using a tool to get a job done.
They stick to the pattern in all the most meaningful ways. At the same time, however, in the true nature of a framework (which is generally outside the scope of a pattern description), they try to give you tools which make very light work of the actual development. If you don't have a pressing need to separate your domain models from your presentation models, you don't have to. One model can play both roles. If you don't have a pressing need to abstract your data access behind, say, a repository pattern, you don't have to. You can throw together some quick Entity Framework functionality directly in your Models and be done with it.
Ultimately it's up to the needs of the project, the preferences of the developer(s), and so on. The patterns are more academic, the frameworks are more pragmatic. Balancing the two is the key.
I guess the distinction is that in asp.net MVC you can have strongly typed views which have 'knowledge' of your model and the entity being passed through to the view. In its purest sense though the View shouldn't (or rather, neednt) have any knowledge of the model. For that reason I say Steven Sandersons example is better.
Fantastic book by he way!
I wouldn't sweat it - Stephen Sanderson's diagram is showing less of the cycle but in more detail.
I'd interpret the MS article arrows as:
Controller populates model (from services, etc)
Controller directs to view
View populates through binding model
The microsoft diagram isn't really that useful or informative or useful though in my opinion. You could equally argue that arrows could go in different directions - or even in both directions like Sanderson's do. E.g. Controller also received models from binding, etc.
The Sanderson arrows are annotated well and are self-explicit, and the book is great.

MVC and NOSQL: Saving View Models directly to MongoDB?

I understand that the "proper" structure for separation-of-concerns in MVC is to have view-models for your structuring your views and separate data-models for persisting in your chosen repository. I started experimenting with MongoDB and I'm starting to think that this may not apply when using a schema-less, NO-SQL style database. I wanted to present this scenario to the stackoverflow community and see what everyone's thoughts are. I'm new to MVC, so this made sense to me, but maybe I am overlooking something...
Here is my example for this discussion: When a user wants to edit their profile, they would go to the UserEdit view, which uses the UserEdit model below.
public class UserEditModel
{
public string Username
{
get { return Info.Username; }
set { Info.Username = value; }
}
[Required]
[MembershipPassword]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[DisplayName("Confirm Password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[Email]
public string Email { get; set; }
public UserInfo Info { get; set; }
public Dictionary<string, bool> Roles { get; set; }
}
public class UserInfo : IRepoData
{
[ScaffoldColumn(false)]
public Guid _id { get; set; }
[ScaffoldColumn(false)]
public DateTime Timestamp { get; set; }
[Required]
[DisplayName("Username")]
[ScaffoldColumn(false)]
public string Username { get; set; }
[Required]
[DisplayName("First Name")]
public string FirstName { get; set; }
[Required]
[DisplayName("Last Name")]
public string LastName { get; set; }
[ScaffoldColumn(false)]
public string Theme { get; set; }
[ScaffoldColumn(false)]
public bool IsADUser { get; set; }
}
Notice that the UserEditModel class contains an instance of UserInfo that inherits from IRepoData? UserInfo is what gets saved to the database. I have a generic repository class that accepts any object that inherits form IRepoData and saves it; so I just call Repository.Save(myUserInfo) and its's done. IRepoData defines the _id (MongoDB naming convention) and a Timestamp, so the repository can upsert based on _id and check for conflicts based on the Timestamp, and whatever other properties the object has just get saved to MongoDB. The view, for the most part, just needs to use #Html.EditorFor and we are good to go! Basically, anything that just the view needs goes into the base-model, anything that only the repository needs just gets the [ScaffoldColumn(false)] annotation, and everything else is common between the two. (BTW - the username, password, roles, and email get saved to .NET providers, so that is why they are not in the UserInfo object.)
The big advantages of this scenario are two-fold...
I can use less code, which is therefore more easily understood, faster to develop, and more maintainable (in my opinion).
I can re-factor in seconds... If I need to add a second email address, I just add it to the UserInfo object - it gets added to the view and saved to the repository just by adding one property to the object. Because I am using MongoDB, I don't need to alter my db schema or mess with any existing data.
Given this setup, is there a need to make separate models for storing data? What do you all think the disadvantages of this approach are? I realize that the obvious answers are standards and separation-of-concerns, but are there any real world examples can you think of that would demonstrate some of the headaches this would cause?
Its also worth noting that I'm working on a team of two developers total, so it's easy to look at the benefits and overlook bending some standards. Do you think working on a smaller team makes a difference in that regard?
The advantages of view models in MVC exist regardless of database system used (hell even if you don't use one). In simple CRUD situations, your business model entities will very closely mimick what you show in the views, but in anything more than basic CRUD this will not be the case.
One of the big things are business logic / data integrity concerns with using the same class for data modeling/persistence as what you use in views. Take the situation where you have a DateTime DateAdded property in your user class, to denote when a user was added. If you provide an form that hooks straight into your UserInfo class you end up with an action handler that looks like:
[HttpPost]
public ActionResult Edit(UserInfo model) { }
Most likely you don't want the user to be able to change when they were added to the system, so your first thought is to not provide a field in the form.
However, you can't rely on that for two reasons. First is that the value for DateAdded will be the same as what you would get if you did a new DateTime() or it will be null ( either way will be incorrect for this user).
The second issue with this is that users can spoof this in the form request and add &DateAdded=<whatever date> to the POST data, and now your application will change the DateAdded field in the DB to whatever the user entered.
This is by design, as MVC's model binding mechanism looks at the data sent via POST and tries to automatically connect them with any available properties in the model. It has no way to know that a property that was sent over wasn't in the originating form, and thus it will still bind it to that property.
ViewModels do not have this issue because your view model should know how to convert itself to/from a data entity, and it does not have a DateAdded field to spoof, it only has the bare minimum fields it needs to display (or receive) it's data.
In your exact scenario, I can reproduce this with ease with POST string manipulation, since your view model has access to your data entity directly.
Another issue with using data classes straight in the views is when you are trying to present your view in a way that doesn't really fit how your data is modeled. As an example, let's say you have the following fields for users:
public DateTime? BannedDate { get; set; }
public DateTime? ActivationDate { get; set; } // Date the account was activated via email link
Now let's say as an Admin you are interested on the status of all users, and you want to display a status message next to each user as well as give different actions the admin can do based on that user's status. If you use your data model, your view's code will look like:
// In status column of the web page's data grid
#if (user.BannedDate != null)
{
<span class="banned">Banned</span>
}
else if (user.ActivationDate != null)
{
<span class="Activated">Activated</span>
}
//.... Do some html to finish other columns in the table
// In the Actions column of the web page's data grid
#if (user.BannedDate != null)
{
// .. Add buttons for banned users
}
else if (user.ActivationDate != null)
{
// .. Add buttons for activated users
}
This is bad because you have a lot of business logic in your views now (user status of banned always takes precedence over activated users, banned users are defined by users with a banned date, etc...). It is also much more complicated.
Instead, a better (imho at least) solution is to wrap your users in a ViewModel that has an enumeration for their status, and when you convert your model to your view model (the view model's constructor is a good place to do this) you can insert your business logic once to look at all the dates and figure out what status the user should be.
Then your code above is simplified as:
// In status column of the web page's data grid
#if (user.Status == UserStatuses.Banned)
{
<span class="banned">Banned</span>
}
else if (user.Status == UserStatuses.Activated)
{
<span class="Activated">Activated</span>
}
//.... Do some html to finish other columns in the table
// In the Actions column of the web page's data grid
#if (user.Status == UserStatuses.Banned)
{
// .. Add buttons for banned users
}
else if (user.Status == UserStatuses.Activated)
{
// .. Add buttons for activated users
}
Which may not look like less code in this simple scenario, but it makes things a lot more maintainable when the logic for determining a status for a user becomes more complicated. You can now change the logic of how a user's status is determined without having to change your data model (you shouldn't have to change your data model because of how you are viewing data) and it keeps the status determination in one spot.
tl;dr
There are at least 3 layers of models in an application, sometimes they can be combined safely, sometimes not. In the context of the question, it's ok to combine the persistence and domain models but not the view model.
full post
The scenario you describe fits equally well using any entity model directly. It could be using a Linq2Sql model as your ViewModel, an entity framework model, a hibernate model, etc. The main point is that you want to use the persisted model directly as your view model. Separation of concerns, as you mention, does not explicitly force you to avoid doing this. In fact separation of concerns is not even the most important factor in building your model layers.
In a typical web application there are at least 3 distinct layers of models, although it is possible and sometimes correct to combine these layers into a single object. The model layers are, from highest level to lowest, your view model, your domain model and your persistence model. Your view model should describe exactly what is in your view, no more and no less. Your domain model should describe your complete model of the system exactly. Your persistence model should describe your storage method for your domain models exactly.
ORMs come in many shapes and sizes, with different conceptual purposes, and MongoDB as you describe it is simply one of them. The illusion most of them promise is that your persistence model should be the same as your domain model and the ORM is just a mapping tool from your data store to your domain object. This is certainly true for simple scenarios, where all of your data comes from one place, but eventually has it's limitations, and your storage degrades into something more pragmatic for your situation. When that happens, the models tend to become distinct.
The one rule of thumb to follow when deciding whether or not you can separate your domain model from your persistence model is whether or not you could easily swap out your data store without changing your domain model. If the answer is yes, they can be combined, otherwise they should be separate models. A repository interface naturally fits here to deliver your domain models from whatever data store is available. Some of the newer light weight ORMs, such as dapper and massive, make it very easy to use your domain model as your persistence model because they do not require a particular data model in order to perform persistence, you are simply writing the queries directly, and letting the ORM just handle the mapping.
On the read side, view models are again a distinct model layer because they represent a subset of your domain model combined however you need in order to display information to the page. If you want to display a user's info, with links to all his friends and when you hover over their name you get some info about that user, your persistence model to handle that directly, even with MongoDB, would likely be pretty insane. Of course not every application is showing such a collection of interconnected data on every view, and sometimes the domain model is exactly what you want to display. In that case there is no reason to put in the extra weight of mapping from an object that has exactly what you want to display to a specific view model that has the same properties. In simple apps if all I want to do is augment a domain model, my view model will directly inherit from the domain model and add the extra properties I want to display. That being said, before your MVC app becomes large, I highly recommend using a view model for your layouts, and having all of page based view models inherit from that layout model.
On the write side, a view model should only allow the properties you wish to be editable for the type of user accessing the view. Do not send an admin view model to the view for a non admin user. You could get away with this if you write the mapping layer for this model yourself to take into account the privileges of the accessing user, but that is probably more overhead than just creating a second admin model that inherits from the regular view model and augments it with the admin properties.
Lastly about your points:
Less code is only an advantage when it actually is more understandable. Readability and understand-ability of it are results of the skills of the person writing it. There are famous examples of short code that has taken even solid developers a long time to dissect and understand. Most of those examples come from cleverly written code which is not more understandable. More important is that your code meets your specification 100%. If your code is short, easily understood and readable but does not meet the specification, it is worthless. If it is all of those things and does meet the specification, but is easily exploitable, the specification and the code are worthless.
Refactoring in seconds safely is the result of well written code, not it's terseness. Following the DRY principle will make your code easily refactorable as long as your specification correctly meets your goals. In the case of model layers, your domain model is the key to writing good, maintainable and easy to refactor code. Your domain model will change at the pace at which your business requirements change. Changes in your business requirements are big changes, and care has to be taken to make sure that a new spec is fully thought out, designed, implemented, tested, etc. For example you say today you want to add a second email address. You still will have to change the view (unless you're using some kind of scaffolding). Also, what if tomorrow you get a requirements change to add support for up to 100 email addresses? The change you originally proposed was rather simple for any system, bigger changes require more work.

How to avoid needing a VIewModel for every Model

I'm using ASP.NET 4 and MVC3.
Often, I find that I need a ViewModel to display information for my Model. For example, take the following model
class Profile
{
public int UserID { get; set; }
public string Name { get; set; }
public DateTime DOB { get; set; }
}
There is a requirement to hide the UserID, but to show the UserName, so often time for models that are similar to the one above, I have to come up with a ViewModel with just the UserID changed to UserName:
class ProfileViewModel
{
public string UserName { get; set; }
public string Name { get; set; }
public DateTime DOB { get; set; }
}
Are there any ways?
Until recently I always passed my models to my action methods as I also thought that creating viewModels with the same property names was duplication (its not). This caused me a lot of pain. I have now been re-educated and almost always use viewModels exclusively in my action methods (of course there will always be situations were it is fine to pass the model directly to the action method).
Have a read of this post which is the one that converted me to using viewModels. This will tell you the following:
The difference between models and viewModels
When each should be used.
How to avoid some security issues with the default model binder.
On top of the information in the linked post you should also consider things such as validation. I had a model that implemented the IValidateableObject interface to ensure the entity was in a valid state before being saved to the database.
In my ASP.NET application I wanted to create a multi-step form that allowed the user to enter the information over a number of pages. The problem I had here was that ASP.NET also uses the IValidatableObject interface during the model binding process.
If you are only allowing the user to enter a subset of the information required for the entity, the model binder will only be able to fill in the information that was given. Depending on how complex your validation is, this can result in the ModelState being marked as invalid as the entire entity is not valid.
The way I got around this was to have a viewModel representing each step each with its own validation. This way you are only validating the properties at each step. Once you get to the final step and everything is valid, I create an appropriate entity using the information given by the user. This entity will only have database-level validation checks performed upon it (field lengths etc.)
My suggestion is not to avoid viewModels but to understand why they are used and embrace them.
No, there isn't, once a member is public, it's public. Now, if the UserID property was internal, then you wouldn't have that problem.
However, one of the aims of MVVM here is to encapsulate logic regarding the interaction of the model and the view. Even if you have the view model and model in separate assemblies and make the UserID property internal, you should still have a view model; if changes come down the line where more functionality is required than simply binding to the model, you are prepared.
Direct access to the model is always a no no.
Additionally, if you really wanted, you could always use T4 templates to auto-generate the code for you (you could use Code DOM on the original CS file) to output your view models for you.
I usually have multiple ViewModels per model - the tradeoff you have to make comes down to this:
Are you comfortable coupling business logic (data annotations, display information, etc...) with your (persistence) models?
Are you comfortable doing all of the hide / display business logic purely within the View and not use the Controller + scaffolding to make those decisions for you?
The downside of creating all of those ViewModels of course is sub-class explosion, but the right way to think about it is in terms of the questions I listed IMHO.

Resources