Asp.Net MVC5, structuring large projects. Areas? - asp.net-mvc

I come from an Asp.Net background and I'm evaluating Asp.Net MVC for a new project. I can't see how to structure a large project adequately.
I'm happy with the Model/View/Controller architecture and I'm presently trying to get Areas to work (which seems quite complicated for what it is).
Can you have Areas within Areas?
Can you put Views in dlls?
I really need a starting point here, are there are resources which show how to structure large MVC projects, assume that eventually there will be 100+ views in the project, I don't want them all in the same folder and ideally I'd like sub folders
thanks for any help
Edit:
I can see that each controller maps to a View folder, what I want is something more like this
Areas
Mail
Absence
SimpleAbsenceController.cs
ComplexAbsenceController.cs
Overtime
SimpleOvertimeController.cs
ComplexOvertimeController.cs
Etc
Edit2: Perhaps this is more of a routing question, can I map from:
http://www.mystuff.com/SimpleAbsence/Index
to Mail/Absence/SimpleAbsenceController
Fundamentally I want a way of structuring my project into folders

I hate answering my own question as I feel it undermines the work of others who try to help, at the same time others may look at this later and these really are newbie questions, so...
(this is all from reading Pro ASP.Net MVC5, good book)
I wanted to know how much flexibility there is in Asp.Net MVC with regard to using subfolders or dlls. This answer address the subfolders question.
Answers
You can put controllers where-ever you like in terms of folders on the disk, these are compiled, but...
When you use areas the MapRoute in the AreaRegistration.cs file automatically limits
the routes to the namespace for the area. So if for example you move a controller to an area you -must- change the namespace or methods like Url.Action will fail
Views must stay where they are, so for a controller called Fred there must be this structure:
View
- Fred
- Action1
- Action2
- etc
You can work around all of this using your own routing system, you could probably work around the namespace issue with a custom route, but my view is as a newbie you should work with the system until you know enough to fully understand the consequences of breaking the rules
So this means you could have a large project with a few hundred Views all lumped together in one folder. It's not quite as bad as it seems as the controllers can be in sub folders and you can directly map from them to the Views.
You also have flexibility in the routing system, so regardless where controller are on disk you can have any urls you like!
e.g. this route maps from
http://www.example.com/App/DoSomething to
http://www.example.com/Home/Something with no changes necessary
routes.MapRoute("NewRoute", "App/Do{action}", new { controller = "Home" });
NB If you do this make sure to use Html.ActionLink or Url.Action (or equivilents) as opposed to direct links, these are clever enough to generate the correct urls based on the routing.
As I say, complete newbie issues but I'm sure others will have the same questions, thanks to MiniRagnarok for his example of a real life project

What we're talking about here is very opinion based. I've seen people that prefer to have lots of Controllers with a mapping of every object to a Controller. I've also seen people that prefer to have tons of Views. So my example is what our team has decided to do and not necessarily the same as you would see in sample tutorials.
Take a project we did that has 200+ Views for example. The site is an auction and retail site.
Controllers
AccountController.cs
AdminController.cs
AuctionController.cs
HomeController.cs
PhotoController.cs
StoreController.cs
SupportController.cs
Views
Account
DisplayTemplates
EditorTemplates
ChangePassword.cshtml
_Favorites.cshtml
Settings.cshtml
Admin
Auction
Home
Photo
Shared
Store
Support
For us, we name all partial views with an underscore first. We also utilize DisplayTemplates and EditorTemplates. All of this really helps us keep things separate. You'll notice that our controllers are split by role or function. We were never bothered by the fact that there are many ActionResults within our controller since all of our logic is really in the models.

Related

ASP.NET Core Nested / Tiered Controllers

Hi there fellow Overflowing Stackers! Looking for your help in regards to having tiered or nested controllers in asp.net core
So far from what I can see, the default boilerplate code, and its default route {controller=Home}/{action=Index}/{id?} only allows for controllers to be in the default Controllers directory, which doesn't allow nesting at all.
From what I have seen thus far there are a few ways to get around this, neither which are ideal in my opinion.
Razor View Pages
Out of the box, it would appear that Razor Pages, automatically circumvent this issue as the .net core automatically attempts to traverse the corresponding folder structure from the associated URL structure to attempt to find a .cshtml file that matches the route.
The problem? This is more of an MVVM pattern than an MVC one. Which is the lesser of the 3 evils, in my opinion, (Open to debate ofc)
Route Attributes
The other alternative I see is that controllers can be associated with routes using the Route Attribute on Controllers and Actions [Route("parent/route/path")]
The problem? Same namespace (folder) means no reuse of Controller names and given the nature of our app, we need to namespace our Controllers. Not to mention that it's going to make the Controller Folder Massive, with 100's of Controller Files.
Adding More Routes
Adding more routes manually is going to be painful, as I have to add a new route for every possible permutation of parent and child within the folder structure.
Whilst I understand that this may be the intended way of doing things. Adding every possible nested folder in a new route is bad design in my opinion. As this is something that can automatically be inferred from the route to the folder structure. And is automatically done in other Languages and Frameworks automatically. (One excellent example C# Class Libraries)
Salt in the Wound
Most importantly it is apparently not possible to have the same named controller in two completely separate folders / routes:
How to use same controller name in different namespaces. When this happens you get greeted with an Exception AmbiguousActionException: Multiple actions matched.
The biggest pain point for me is that Namespaces are supported within the normal version of the .NET MVC Framework. For some wonderful reason, the namespace parameter has been removed from the MapRoute() method by someone at Microsoft. Scratching my head as to why that was done?
Not 'Just' a Rant
Before I continue, this post is not me whining or ranting, I am genuinely looking for a better solution and am looking for other ideas and alternatives. Please keep reading for my ideal solution below.
Ideal Solution
Since I have come from a PHP background I have found that simply using the default spl_register_autoloader() gave me exactly what I wanted. The capacity for me to register a specific namespace of my choosing and for PHP to look at any and all parts of the subsequent namespace in the local directory folder structure for the Controller I wanted.
i.e. the PHP controller Controllers\NestingLevel1\NestingLevel2\HomeController would look for the associated controller in Controllers\NestingLevel1\NestingLevel2\HomeController.php
Simple, Beautiful and Did I mention Simple?
Wrap Up
Is there any way I can get Nested Controllers in ASP.NET core without:
Razor View Pages (MVVM)
Route Attributes on Every Single Nested Controller
Manually Adding Routes for Every Possible Nested Parent / Child Combination

ASP.Net MVC Default Files Structure

Is there any functional reason of the default files structure on new ASP.Net MVC Application (Grouped by controllers, model, views etc. ?
Otherwise I would structure it in a way that would be more convenient for me.
Thanks!
Technically, you can put models and Controllers anywhere, since they're just code files that get compiled into a DLL. Other files, however, have stricter location requirements if you want to take advantage of the conventions that MVC asssumes.
Strictly speaking, you can place views anywhere. However, doing so has a number of consequences. You must specify the full path to the view in your View() method, and if you don't put views in the ~Views folder, then it's possible for people to download them directly (which you don't want).
In general, MVC works a lot more smoothly if you follow the conventions. If you go your own way, you lose a lot of automation and productivity.

MVC 3 project structure

I am trying to find the best way to layout my MVC 3 project. When searching online I came across a suggestion that basically said right click on project and add area. What this did was create an area folder with same controller/view/model structure in the same project. This is not what I want. I want the flexibility of having separate projects. I will keep only the views in the main web project. Everything else in a separate project.
Towards that attempt I created a separate project for my controllers. Now I am stuck with pointing a controller action to a view. In all the online examples it was right click and add view. This being a class library project I don't have that flexibility. Where am I going wrong?
All examples that I have found including the ones I have gone through on Asp.net basically explain how to create study applications, which is only good for learning purposes. A large commercial application can't possibly have all the views/models/controllers in one project. Or is that the way it is supposed to go in MVC? I am not sure if doing everything with mouse clicks is also a good idea. In the webforms world also there were a lot of study-for-beginners applications that used mouse clicks to create basic CRUD applications, but in real commercial projects, we never used those methods.
What are your thoughts, guidance on this?
Thanks for your time...
MVC is based on a convention; the convention is you put all the views on /views, the models in /models and the controllers in /controllers. You can change the convention but it will not make your life easier.
From a conceptual point of view this does make sense. If you keep all domain logic and data access in separate projects all you are left with is the web related stuff, your controllers, view models and views. That's your MVC project.
Note that if you want to split off parts into separate projects you may find portable areas useful.
I don't see why you can't use the built in generators as a base for your views and controllers? Nothing says that you have to leave them as generated. I personally thinks that's it's really nice to get a base generated for me (with mouse clicks).
The MVC project is just a UI layer. It's madness to put logic in it for large scale applications. It's therefore usually fine to have one project for all the UI. It actually makes it easier to get an overview of the UI.
That said, there are ways to get a plugin based solution where you can move the controllers (, models and views) to class libraries. But it's not easy.
You need to create a virtual path provider (to find the views)
Make all views embedded
Modify the project file to get the "Add view" dialog etc.
Use areas (makes it easier)
Tell the BuildManager that your plugin DLL exists.
You also need to modify the virtual path provider to access the views from your plugin folders if you want to be able to modify the views during runtime in visual studio. Any change would otherwise require a rebuild of the plugin DLL.
Update
Video for MVC2 (MVC3 areas works the same): http://www.asp.net/mvc/videos/mvc-2/how-do-i/aspnet-mvc-2-areas
Do note that that video is for areas in the same project. Having areas in separate class libraries are more complex. The easiest solution is to use the portable areas as suggested by someone else.
Why keep only your views in the 'main web project' - I think you are missing the point with MVC.
It's the controllers that are your 'main web' part. They are what your users request and post back to, not the view.
The view is only there to provide a means to layout HTML for the controller to push to the browser.
The Models which I think should really be ViewModels, are there to provide substance (i.e. real data) for your views.
So you can see that the MVC layout really wants all three of these to be grouped sensibly together. Controllers interact with your user, get the view (the layout) and populate it with your ViewModel/Model (the data). This is your user interface, all three parts of MVC (if you go with the ViewModel anyway) are only for UI.
Where the data comes from, your real models and whatever you want to do with it can easily reside in a dll somewhere or on the other side of a set of web services or whatever.

ASP.NET MVC controller actions design

I really like the way ASP.NET MVC works. I'd love to implement it on all new web projects moving forward, but I hit a snag in a prototype the other day that I really haven't found a good solution for, so I ask you, how would you design an MVC app that doesn't fit the typical REST pattern? As an example, the prototype I was designing would have several pages, but the pages themselves aren't necessarily bound to a domain model. For example, take a simple registration site, which might have the following pages:
/Default.aspx
/Register.aspx
/ThankYou.aspx
Occasionally, such a program might require an admin section to deal with such details as moderating sign ups or reviewing data. In a standard ASP.NET web app, I might add the following
/Admin/Default.aspx
/Admin/ListRegistrations.aspx
/Admin/ViewReports.aspx ...
Would it be an unacceptable deviation from the MVC pattern, in this case, to have two controllers such as:
Home->Index
Home->Register
Home->ThankYou
Admin->Index
Admin->ListRegistrations
Admin->Reports
My frustration with this is compounded by the fact that there is no real solid implementation of subcontrollers and areas yet. I'm aware of the "Areas" prototype put together by Phil Haack, but it's not very mature, and quite frankly, I'm not sure I like the way it's setup, but I don't really know how I'd like to see that work either.
I guess when I think MVC, I tend to think REST as well, and having controller actions that represent pages rather than actual entities or actions doesn't sit right with me. What do you think?
You can always mix ASP.NET Web Forms with MVC.
Just add
routes.IgnoreRoute("Pages/{*path}");
to your routing table and add traditional Web form pages to Pages folder of the application.
One mistake that newcomers to MVC make is to group actions into a controller for display reasons. In your case, instead of grouping the Register and ThankYou actions in with the homepage try separating them out into an AccountController as the MVC team has done in the sample project. You can use routing to set the Url's up however you want for the end-user.
As for your other actions, how about a ReportController? You could then additionally have an AdministrationController whose Index action/view contains links to various admin actions, including those on the ReportController.
Short Version: Group actions into a controller by function, not site navigation.
I usually ditch the "Home" controller as the first thing in a project and replace it with a "Page" controller. I use that one for anything that is "just" a page. Things like "FAQ", "Contact Us", etc. I do this at least partially because the default approach to the Home controller requires a new method being added every time you need even a basic, static page.
In that controller, I only have the one action: Display. That action gives all of those pages the same context object. I actually store the content for those pages in the database with a lookup "slug" and tie it into NVelocity templating, but even just static HTML or NVelocity templates in files would work too.
Anything else, like the others said, gets split into controllers by the "thing" being managed. So, a ReportController, User or AccountController, CartController, etc. Then the actions make much more sense.
When you're talking about listing the registered users, it's actually a list of users, so I'd have a UserController and do /User/Display/Registered/MostRecent or something similar. For the registration itself, /User/Register which would post to /User/SaveRegistration which could, in turn, redirect to /User/DisplayProfile/NewUserID or /Page/Display/Home from there.
You can have as many controllers as makes sense; that layout looks reasonable. Note that routes don't have to map directly to {controller}/{action}, but it keeps things simple. Looks fine to me - except I'd probably have ThankYou as a view - i.e. the Register [GET] perhaps uses a different view to Register [POST]

asp.net mvc - subfolders

How does the new Microsoft asp.net mvc implementation handle partitioning your application - for example:
--index.aspx
--about.aspx
--contact.aspx
--/feature1
--/feature1/subfeature/action
--/feature2/subfeature/action
I guess what I am trying to say is that it seems everything has to go into the root of the views/controllers folders which could get unwieldy when working on a project that if built with web forms might have lots and lots of folders and sub-folders to partition the application.
I think I get the MVC model and I like the look of it compared to web forms but still getting my head round how you would build a large project in practice.
There isn't any issues with organizing your controllers. You just need to setup the routes to take the organization into consideration. The problem you will run into is finding the view for the controller, since you changed the convention. There isn't any built in functionality for it yet, but it is easy to create a work around yourself with a ActionFilterAttribute and a custom view locator that inherits off ViewLocator. Then when creating your controller, you just specify what ViewLocator to use, so the controller knows how to find the view. I can post some code if needed.
This method kind of goes along with some advice I gave another person for separating their views out for a portal using ASP.NET MVC. Here is the link to the question as a reference.
In terms of how you arrange your views, you can put your views in subfolders if you'd like and create your own view structure. All views can always be referenced by their full path using the ~syntax. So if you put Index.aspx in \Views\Feature1\Home then you could reference that view using ~/Views/Feature1/Home/Index.aspx.
Here's two good blog posts that I found that may help other readers:
http://stephenwalther.com/blog/archive/2008/07/23/asp-net-mvc-tip-24-retrieve-views-from-different-folders.aspx
This one talks a little more in-depth about what Haacked described above.
http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx
This is a nice alternative for grouping your site into "areas."

Resources