ASP.NET MVC: Grouping classes around controller - asp.net-mvc

In asp.net mvc (4), out of the box, views go into Views folder, and then grouped by controller in subfolders.
Controllers go into Controllers folder, (View/Edit/Input)Models go into Models folder, etc.
I do like the way views are organized. I do not, however, like breaking the rest of the MVC pieces horizontally.
My question is, what would be downsides of leaving views organization structure as it is, but group other classes by controller (i.e. by use-cases). E.g.:
/Home
HomeController.cs
IndexViewModel.cs
IndexViewModelBinder.cs
/Messages
MessagesController.cs
MessagesApiController.cs
MessagesViewModelBinder.cs
MessageViewModel.cs
MessagesListViewModel.cs
/Views
/Home
Index.cshtml
/Messages
MessagesIndex.cshtml
MessageDetails.cshtml

All that matters is the arrangement of the View files because they're accessed at runtime. Everything else is compiled into the assembly so the physical location of their source files is irrelevant.
Like you I find the default arrangement a bit awkward for larger projects, so this is how I lay out my current projects:
~/
/Areas
/DefaultArea // I always use areas, even when there's only one, because it simplifies things when adding additional areas.
/Controllers
FooController.cs
/Views
/Foo
FooView.aspx // Yes, I use WebFormView. Just a matter of personal preference
FooEdit.aspx
FooModels.cs // this file contains my ViewModels
So basically, I put my ViewModel classes in the same folder as the views rather than putting all the ViewModels together (which makes less logical sense). I was tempted to put my Controllers in their views' folders, but I decided against it.
I've found no downsides to my approach so far (been using it almost 2 years now).

I generally like to avoid areas where possible as it creates some issues with routing.
I think your structure is completely fine (and superior to the default MVC/Web structure of separating code based on "type" rather thank "function").
All I would suggest is that you only keep your "web" .cs files in the web DLL (e.g. Controllers, ViewModels, Binders, etc) and have the same structure in separate DLL(s) for Domain / Services / etc layers so they can be reused / tested separately if/as required.

Related

Areas vs Folders in MVC

I am not to relate to Areas in MVC, why cannot we have simple folders to indicate modules, is the web.config which needs to be there, the below is the reason why i am asking this
Views -unfortunately for views it’s not possible. All the views must be placed inside “~/Views/ControllerName” or “~/Views/Shared” folder.
The following article describes in detail the reasons for Areas and the difference between Areas and folder-based conventions in ASP.NET MVC.
http://www.codeguru.com/csharp/.net/net_asp/mvc/article.php/c20227/Using-Areas-in-ASPNET-MVC-Application.htm
The essential idea is contained in the Introduction of the article:
ASP.NET MVC relies on certain folder and class naming conventions to
organize models, views and controllers. A large application often
consists of functionally independent modules with the result that the
main application is essentially a bundle of these sub-applications. In
such cases, organizing various models, views and controllers can be
tedious. Luckily, ASP.NET MVC allows you to split your application
into what is known as Areas. Each area mimics the folder structure and
conventions as required by ASP.NET MVC. This article shows you how
Areas are used in an ASP.NET MVC application.
When someone is trying to develop a sub-module suitable for inclusion in any ASP.NET MVC application (as an example, think deployment/inclusion of 3rd party code via a NUGET package) then the Areas construct is very helpful, and arguably a necessity.
Areas are folder structure which contains its independent set of Controller,
View, Model. Consider we are creating an area called Admin then the folder structure for the Admin area will be,
The same setup can be created by adding folders, Subfolder, and Required files.

Organizing Areas in ASP.Net MVC 5

Get ready for yet another elementary question from me...I think I have a grasp on the Area concept in a MVC site, but I would like to organize them even further, could I either move them to an external project (with controllers, views, scripts, styles) or create sub-folders within the Area folder?
Reason I'm asking is that I have tried to create a folder under Areas and called it Common, then created an area inside that folder and called it MyTest. When I attempt to browse to mysite.com/mytest, it fails.
You should try to go the usual way and use areas as a subfolder of the Areas ASP.NET root folder. The only reason why your URL would fail is that your AreaRegistration file is not properly registering your route. You can check out Glimpse as a way to debug routes or simply look at the files and try to figure it out your self. Keep in mind that ASP.NET automatically look for classes that inherit from AreaRegistration and use them to register routes that are specific to your area. If your routes seem to be configured properly, make sure your controllers are in namespaces that are visible to the route.
If you want to isolate the areas (with the controllers models and views) into separate projets, you should look into creating your own VirtualPathProvider, because that's the only way for your views to be located. However, they would have to be Embedded Resource and couldn't be debuuged. Your area, if located in a separate DLL, would be automatically registered and your controllers would be automatically found as long as the DLL is in the main application Bin folder.

MVC Web Api - barebones minimal project structure

I'm looking at this MVC WebApi starter kit (for Angular/TypeScript)
Ignoring all the client side code, I noticed the author has made a WebApi that is extremely bare bones. Has has taken out most scaffolding including _ViewStart.cshtml, _Layout.cshtml, and forgoed the convention of controllers in Controllers folder and views in View folder under subdirectory with same name of controller, etc.
He added some interesting Routing and Validation classes that I havent seen before in a Core folder and put controllers in Api folder and Views directly into Views folder with an Index.cshtml at the root.
It's very clean and barebone project structure for a standalone web api that will do nothing except serve data to a client heavy application. I kind of like it this way but before jumping ship I'm wondering what drawbacks this approach has and if I'm actually giving up any core features of the framework by doing it this way. For example, clearly MVC Areas are being given up here in favor of flexibility to create your own view folders structure and seperation of application sections (I'm okay with getting rid of MVC Areas I rarely used them anyways). Another thing is I don't think a Controller action method can return View() and it will find it in the Views folder by convention of the controller name. I'm also okay with that since I will only be serving JSON data and will use 100% client side templating.
Are there any other core features that are being abandoned that I'm missing that may make me regret going with this project structure?
When I create Web APIs that are hosted in IIS, the only files in my web application are web.config, global.asax and global.asax.cs. Everything else is not required.
Take a look at this template if you haven't already before you decide how to structure your ASP.Net MVC / Angular project:
http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83
You can always add components into your project later, so I wouldn't seat it too much. I like to start with a lean/mostly empty project first and add things myself so that I fully understand what I'm adding.

ASP.NET MVC 3 Structure - Go to view in another project

I've got the following project setup
Project A (main)
Business
Data
View (asp.net mvc 3 project)
Project N
Business
Data
View (asp.net mvc 3 project)
How can I call from Project A the View in Project N and from N back to A. Essentially what I'm trying to do is package each Project N to have its own individual MVC as it comes from different sources and plug it in to the main project and then just have it navigate to the correct view.
Can this be done? Or is there a better way to do this?
You could write a custom virtual path provider. Here's a nice blog post which shows an example of such a virtual path provider allowing you to embed Razor views into assemblies as resources and reusing them in multiple applications.
Unfortunately without a custom virtual path provider, you cannot cross reference views between multiple ASP.NET MVC applications. This simply is not allowed by the default provider which looks for views only inside the current application.
I do sugest another approach if possible. if I understood correctly, those projects are somehow ike plugins but they are not standalone applications.Also they now about each others so they are coupled. It's, let's say tricky, but I would use only 1 asp.net mvc project (the web ui). All the UI bits which belong to other projects I'd make them helpers (pretty much widgets). This means, that each project contains only the helpers which will be used to construct a view.
I think it's a bit of an architectural problem if you only want to keep the views in each project just for the sake of hosting them in a different assembly. Going the widgets' way it might seem mkore work, but I think you gain the most control and the separation level you want. The only thing is you don't have full Views defined, but why you would want to have full Views (partials, layouts) in separate places if they will be used in one place only?!
Now, if each project is indeed a plugin, independent of other plugins, then going with compiled views is the best way. But if Project B knows about the view of Project N, then I think the above solution is more suitable. That or the whole app is too over engineered. Separation is good when it doesn't create a whole new jungle to navigate it.

ASP.NET MVC - Strongly typed view model, where does it belong?

I'm trying to create a strongly typed view model as John Sheehan suggests here. Where should it go? I can make arguments to myself for Model, View, and Controller.
It should go in the "Models" directory of the web app. ViewModels are by definition specific to one or more views and therefore belong in the web app, not the core.
You could define them in the controller that uses them, but this doesn't scale. Same with defining the class in the view code. Even though one-class-per-file means more files, its easier to find code and easier to maintain.
I'll often create a subfolder for each controller, so I end up with things like Web.Models.Foo.BarViewModel.
If have them in my Domain project in a PresentationModel directory and like #Seth Pretry-Johnson, I have them in separate Controller directories.
This is my overall structure of a project:
Website Project
Controllers
Views
Etc
Domain Project
Models
Repositories
Abstract
Services
Abstract
PresentationModels
Home
User
Etc
DataAccess Project
Repositories
HTHs (and doesn't raise more questions.. ;-),
Charles
I put the actual model class in the Models folder.
/Controllers
/Models
/Entities
/Mappings
/ValueTypes
/ViewModels
Something like that. I'm a big fan of the Fluent NHibernate.
It can go wherever you want it to go, why do you need someone to tell you where to put a class?
A lot of people have the wrong idea that, unless you put your classes inside some specific directory grouped by functionality, things will not work. This might be true with other frameworks, but with ASP.NET MVC it's not true. Code is compiled to assemblies.

Resources