ASP.NET MVC: convention for organizing ViewModels - asp.net-mvc

As discussed throughout the various MVC questions and blogposts, we know that the ASP.NET MVC project layout is heavy on convention.
I blindly made a sub-directory in the Controllers folder.
This doesn't feel right.
alt text http://www.imagechicken.com/uploads/1252003002097179400.png
Question: What's the common accepted convention on which directory to store your ViewModels? What are your suggestions or what is the established convention?

I use a "Models" folder alongside Controllers and Views. The same one which is empty in your project (I don't use Areas).
The "M" in "MVC" model goes in a separate assembly. The only models in the web assembly are presentation/edit models.
Inside the Models folder, there are subfolders by namespace as usual. So I have:
Vertex.Data (Assembly with repositories, etc.)
Vertex.Web
Controllers
BarController
FooController
Models
Bar
BarListItem
Foo
FooDetail
FooListItem
Views
Bar
Foo
Shared
...etc.

I typically create a model for every view. Even if it is just an exact map of some other object in my project that I could be using. This way my view and it's required model is decoupled from the rest of the application. It also makes adding data to the view in the future very easy by just extending your view's model.
It takes a little more work up front and sometimes seems like your duplicating objects but I just prefer the seperation.
I store all my view models in the models directory created in an MVC project. Those 'models' map one to one to my views. I use subfolders within the Models folder if the view models become more than just basic data holders. The subfolders would contain all the bits and pieces required to represent that view.

I think the idea is that (View)Models should go in the Models directory (which is empty when you create a new ASP.NET MVC project).
Personally, it makes more sense for me to arrange namespaces around features instead of mechanics, but while this is of no consequence with regards to Models, it would have some implications when it comes to Controllers and Views.

Related

Separate Models between 2 MVC projects?

I have 2 Projects. A mobile application and a standard website.
I want to share my models between the 2 projects using Entity Framework - Code First.
How do I acheive this?
I looked at this Q:
MVC and separate projects,
does this mean I should only put my DTOs in the separate assembly?
Is it possible and/or wise to put both View Models and DTOs inside a separate project?
If so, can I also put my model queries inside this separate assembly?
And an example to help project my thoughts:
ExtAssembly.Product product = new ExtAssembly.Product();
product.Name = "Dave";
ExtAssembly.ProductQueries.Create(product);
var products = ExtAssembly.ProductQueries.Search("Dave");
Is it possible and/or wise to put both View Models and DTOs inside a separate project?
Yes, it is possible, however, it might not be the right separation. View models usually are bound to the View, so they would usually stay closer to the View than the Model. I'm not sure what role your DTOs are playing here, but you want to ask yourself what concern (M,V or C) owns them and then group them there.
If so, can I also put my model queries inside this separate assembly?
Based on your example, placing the Model and your model queries in a separate assembly seems sensible. I have seen the Model separated into a new project many times. It doesn't make sense always to package the Model in the same assembly as your controllers or view for exactly the reasons you are stating in your question.
Namely, you usually want to use your Model (where the core business logic exists) for more than one UI.

ASP MVC 3: Is dependency injection in ViewModels a good idea?

I am facing a design issue with an mvc 3 app. I have a viewmodel ProductCreateModel that has a list of Categories.
Now I am setting the Categories list in the controller, but I am thinking if it is a good idea to indect the datasource in ProductCreateModel constructor.
Do you think that view models should be fat models that also know to read dependent data from the data source? ... or this is a controller thing?
I prefer slim viewmodels that do not know a thing about data layer. They are easier to manage (in my experience).
I think view models should be light models, and the only way for them to read related data, should be properties on "parent" object, the model they actually wrap.
Most of the time my view models are just classes with properties, all logic are in the controller or in a service class (if we're talking a lot of logic that would otherwise be put in the controller). All this is in the name of easier testing.
When I learned MVC I was taught that the "rule of thumb" is Skinny Controllers, Fat Models, Dumb Views. A mistake that many MVC developers make is Fat Controllers (too much logic), Skinny Models (basically POCO classes to hold data), and Smart Views (a bunch of Razor Syntax with If this, Else that, etc.)
Over the years I've stuck to the Skinny Controllers, Fat Models, Dumb views approach, and it has worked well for me. Now, take into consideration that this is related to Models and not ViewModels. Usually your Models should be in an entirely different layer (i.e. proj or folder). ViewModels, on the other hand, should be fairly simple. This makes them easier to test, and more reusable. If you are finding that you need some sort of service, repo, or other dependency to build up your ViewModels, then you should probably abstract that logic out into some sort of Composer Class. In the past I've used a ViewModelManager which implements IViewModelManager, to compose my ViewModels if need be. This way you can inject IViewModelManager into your controller, and use it to build your ViewModels. Then, in your ViewModelManager implementation, you can inject your other dependencies, like repos, services, etc. to actually construct your ViewModel.
This approach definitely requires more code, and many more classes, but it will give you a good level of granularity, and separation, plus support the DRY principle along with Single Responsibility.
Happy Coding!
As a general rule, I don't think you want to do that.
As an exception to that rule, I've started using a little bit of Service Locator in my Editor Templates when creating drop downs. I've gone through multiple ways of populating drop downs (generally, some form of adding a collection to either the view model or into view data). I saw a video where SL was used in the Editor Template to get the data and then convert to a Select List. My initial reaction was "ugh, really?", but, the more I thought about it, it made sense.

ASP.NET MVC - separating large app

I've been puzzled by what I consider a contradiction in terms: ASP.NET MVC claims to be furthering and supporting the "separation of concern" motto, which I find a great idea.
However, it seems there's no way of separating out controllers, model or views into their own assembly, or separating areas into assemblies.
With the fixed Controller, Model and View folders in your ASP.NET MVC, you're actually creating a huge hodge podge of things. Is that the separation of concerns, really?? Seems like quite the contrary to me.
So what I'm wondering:
how can I create an ASP.NET MVC solution that will either separate out controllers, the model, and the folders full of views, into separate assemblies?
how can I put areas of ASP.NET MVC 2 into separate assemblies?
or how else do you manage a large ASP.NET MVC app - which has several dozen or even over a hundred controllers, lots of model and viewmodel classes, and several hundred views?
I think you're looking for Areas in ASP.Net MVC 2. There are some things to uncomment in the CSProj files, but after that it will copy the views over when you build. I don't think there is any requirement that the Controller or Model classes be in the same assembly as the views.
Walkthrough: Creating an ASP.NET MVC Areas Application Using Multiple Projects
Controllers: AFAIK you shouldn't have to do anything special to throw controllers into their own assembly. At the very most all you'd have to do is override the GetControllerType method of your ControllerFactory.
Models: Zero restrictions on where you put your models. Although this is frowned upon I regularly use persistent objects from an Nhibernate/other ORM layer or WCF/service layer DTO thats are located in a separate assembly as my views. This works the same way using WebForms.
Views: Views in a separate assembly must be marked as embedded resource and then you must use a custom VirtualPathProvider that knows how to get the views from an resource instead of the file system. views from an resource instead of the file system. Again this is the exact same technique you would use for WebForm development.
Regarding mcintyre321 and his Portable Areas answer: The linked project does barely anything custom and simply wraps up the existing MVC 2 extensibility points into an easier to use abstraction. Its barely "custom" and more syntactic sugar.
You manage a large MVC app just like you'd manage any other large app. I dread opening up a 500 page WebForms project because you never quite know whats in each of those code behinds. With MVC distinct functionality is mostly within its right place. Its not contrary at all.
Separating code into separate assemblies is orthogonal to separation of concerns. Where the code lives is not a "concern". Separation of concerns has to do with responsibilities and direction of dependencies of various components. For example, Views are responsible for rendering the output, and the controller knows about the views, but the views don't really have intimate knowledge of the controller.
Likewile, Models don't know anything about either views or controllers, but both views and controllers will know about the model.
However, back to your question. As jfar points out, moving controllers and models into another assembly is trivially easy and will work. Moving views into another assembly is trickier. Embedded resources with a custom virtual path provider is one way, but not one we generally recommend for a high performance site. But if it meets your needs, go for it.
MVC is very extensible and does not require to adhere to the Controller, View, and Model folder structure. You can place the controllers anywhere you would like, however if they are located in another assembly you will need to implement your own controller factory that knows how to locate them. Here is an example for locating your controllers with Windsor.
Your models/view models can be where ever you want. You simply need to reference their namespace in the web.config so views know where to look. (At least I know this is true with the Spark view engine.)
You put your views in any web project. My usual strategy is to create a plain web (non-mvc) project that contains the views folder. (This could even be a legacy web app!) Then all my controllers go in a separate class library. My view models and services go in another.
As far as structuring folders, I usually center my hierarchy around domain concepts. I'd have a folder in each project for Users, Products, Orders, etc. I never have a Models or Controllers folder anywhere.
You need to use portable areas see http://www.lostechies.com/blogs/hex/archive/2009/11/02/asp-net-mvc-portable-areas-part-2.aspx

Best practices regarding locations for ASP.NET MVC models

Are there any best practices that cover the places that ASP.NET MVC models should be defined?
A new ASP.NET MVC project has a nice neat Models folder for them to go in, but in a production environment they can come from other places:
Third party class libraries
WCF services
Is it acceptable for a strongly-typed view to use a class defined in such a location?
In just about every project I have worked on the models of ASP.NET MVC are more View Models than models in the traditional sense of the word. I have yet to have a project where I can use the same Model that I use in my data access for my View Model. There is just too much other information that needs to be displayed on most pages. So for that reason I will either store my models in the models folder or store them in a separate library with all of my other MVC specific classes.
I don't know what you exactly mean by putting models in WCF services. If you mean using WCF services that expose the model object you need, that would work.
Regarding separate class libraries to hold your models, views and controllers, I think that's a pretty common approach and works pretty well. In fact, I believe this is really a requirement when the size and complexity of your application grows. It's a kind of physical separation of the distinct logical components in an MVC app.
One issue that I've found is that, unless the model is defined in the web project, VisualStudio seems unable to find it when using a strongly-typed view specified in markup. My models are usually defined in a separate project and I've found that to use strongly-typed views, I need to create a codebehind so that I have a class that derives from a strongly-typed ViewPage. Then I change the markup and associate it with this class.
You need to import the namespace to the view page. This does not require a codebehind page.
Use the directive
<%# import namespace='your.namespace.here' %>
immediately after the <# Page..... directive

Naming conventions - One rule for Controllers, no rules for Models and Views

In ASP.NET MVC controllers exist in a folder called Controllers. Their names must end Controller otherwise things just don't work (you get an HTTP 404 error).
However, Model names don't have to end Model and View names don't have to end with View.
This seems inconsistent...why (from an MVC or design standpoint) do controller names have to end Controller?
Do other MVC frameworks have this requirement?
Edit
Since this appears to be the convention I am not advocating going against it (see Convention over Configuration!), but I want to understand the reasons behind it.
The controller convention is so routing can easily find the controller without additional configuration. Adding the required Controller ending makes it less likely that you would accidentally expose an object through MVC routing.
There is a built in convention for Views as well. By default views should be in a folder named for your controller and be named the same as the action calling them, this is what enables the method call View() in your action to work without specifying the view. I often find myself specifying the view anyway, but if you are looking for a convention this is definitely the one encouraged by the framework.
From a model standpoint you are correct, there is no standard convention. The reason for this is because the ASP.NET MVC framework never directly touches the models. It needs a convention for the controllers to find them from routing, and it needs a convention for views to find them from the controllers... but models are only accessed from logic in the controller so the framework doesn't need to know about them.
That being said I have seen most people build their Models just like they built their entities or Domain model before MVC. If you are using an active record pattern then name the models to correspond with the tables they are mapped to, if you are focusing more on a domain then name the models to correspond with the part of the domain they are modeling. Also, I have seen more and more people creating a set of view models that are just used for presenting data to the UI and are created by pulling in parts from various models in your domain. Models are definitely the least opinionated part of ASP.NET MVC, but that is a good thing imo since people have very different ways they like to work in this area.
That is just a convention not a requirement! You can change this behavor by customizing the DefaultControllerFactory or creating your own controller factory.
see here for more info. Also there are some examples in MvcContrib project which inject the controller from a Dependency Injection engine. check it out here.

Resources