ASP.NET MVC controller actions design - asp.net-mvc

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]

Related

MVC Application and Controller Design

I am relatively new to MVC and very new to Ruby on Rails. I've been going through Michael Hartl's excellent Ruby on Rails Tutorial for the second time and I have a question about application architecture. In chapter three he creates some static pages with actions from the same controller. Is this common in MVC architecture?
How do you determine between which pages should have the same controller and which pages should have their own individual controller? I assume that customers and contacts would have their own controller, but what about something like a dashboard or contact page, could they maybe go to the same controller?
Actually, static pages aren't really about MVC, think about it: they are static, so they don't have business logic. Basically you'll end up with a VC instead of MVC (the model won't exist).
Usually, for static pages only, unless they need some special routing, you would go with a single controller and a bunch of actions, the direct consequence would be having a directory structure like
views/static_pages/<youstaticpage>.html.erb
That's quite nice, especially if your static pages are really static, so you end up with a maximum of ~10 pages.
The moment you need to pull data from the database, I suggest to extract that page into its own controller. So for example if you store website email/phone/address/whatever in a location and you need to fetch and use it in your About page, I suggest to create your AboutController and handle everything through it.
In this way you'll keep the StaticPagesController very clean. That being said, if you want to strictly stick with MVC, you should have one controller per static page, but would be really worthless in this case. Extract the code when you need it, it will still be very easy: the moment you don't have a simple page, extract it into its own controller.
One important thing I learned from POODR is that code must be good enough. In addition, you should start refactoring when it's needed, over-engineering it's an ugly beast. Believe me, I love over-engineering stuff.

Asp.Net MVC5, structuring large projects. Areas?

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.

ASP.NET MVC Controller design

I have a question about how to design my controllers properly.
Project is fairly simple: blog, immage gallery with categories and images inside them, news secion.
However I don't know how to organize my controllers for this because I want to make somewhat admin panel where administrators can edit, add and modify these things. I've came up with 3 scenariosu so far...
Admin panel will have links to site/controller/edit, but layout for these action results will be different from standard one.
Admin controller will have all these actions like BlogAdd, BlogEdit so that url will be something like /site/admin/blogedit.
Create copies of Blog controller in admin folder so url will be like /site/admin/blog/edit - i sense problems with routing since 2 controllers with same name does not sound like a good idea, however I like ho URL looks in this situation.
What I'm trying to make is CMS somewhat similar to wordpress, where blog creation,editing and deletion is completely separated from default blog itself.
I suggest you stop thinking about URLs and Controllers being a 1->1 relationship. This will make things MUCH easier and less confusing. You can make the URLs work however you want with MVC's routing mechanism and there's no reason to restrict your controller design/organization because of the URLs you want, because you can always adapt the routing to with with the URLs you have in mind.
While building the website, just focus on the controllers (and the general interface) and ignore the URLs until you get to that point, and then when you come up with a good URL scheme go into the routing system and add the routes to connect to your existing controller actions as you want.
Once you code out your blogging engine you will have a much better idea of the user workflow and will probably find different ways to organize your URLs, and you can then reorganize your URLs without touching the controllers themselves.
As to your first requirement:
There are two ways to do this depending on your end goal. If your goal is to display the same core content, but have different user options available (different overall layout, additional buttons on the page, etc..) then the best idea is really to just pass in an IsAdministrator property in your view model, and make the slight changes to the page based on if that's true or false. The reason is because you still (most likely) want the core of the page to be the same, and this keeps you from duplicating code that is related to the core data (data that's being displayed for both admins and non-admins).
Edit: So in summary, organize your controllers based on what makes it easier to develop with, not based on how the user interacts with the system with. You can always change the latter, changing the former is harder and will make maintenance annoying.
You can create Areas in your MVC project and have your admin functionality in a controller in your admin area.
This will allow you to easily seperate your administration functionality from your general blog functionality.
That's how I'd do it.
Why don't you keep the routes the same and handle the different roles via security? For example:
/blog/name-of-topic/view to view a topic (all users)
/blog/name-of-topic/edit to edit a topic (only enabled for logged in users)
/blog/add to create new topics (only enabled for logged in users)
You can handle these actions in a single controller and decorate the actions that require logged users via the [Authorize] attribute. Same thing with the links on your views, you would enable the links to edit and add topics only to visible users.
You could still have a separate panel to allow admins to hit the aforementioned add/edit links .

What is the advantage of using multiple Controller classes in ASP.NET MVC?

I'm just learning the basics of ASP.NET MVC and am wondering what the benefit is in breaking up website logic amongst multiple controllers versus just having a single Controller class that runs the whole website, besides simply organizing code better. (In my opinion, just the latter benefit should not be enough to affect the end user via the url due to separation of concerns: the implementation details of the site should not be being reflected in the urls the site uses, no?)
Some examples on Controllers I've been reading show different controllers for things like "Product" or "User" or "Post". These clearly correspond to classes of objects followed by actions that can be taken on those (looking at the url right now I see stackoverflow.com/questions/ask).
Is there an advantage of splitting up the website into separate controller classes like QuestionsController versus just having a single default controller and handling these actions within it, for example stackoverflow.com/ask-question (besides it looking slightly uglier).
I ask because I'm not particularly interested in making my website RESTful (I looked into it a bit but deemed it too limiting) and instead favour query string parameters to pass information about a request. Therefore, the concept of splitting a url up into controller and action doesn't make sense to me, since the action and class information will be represented in the query string.
Finally, I much prefer the simpler look of urls like www.mysite.com/about versus www.mysite.com/home/about (what does that even mean?), again leading me to wonder what the point of multiple controllers really is.
You can achieve practically any url scheme you desire with ASP.Net MVC Routing. What controllers you have and where your actions live has nothing to do with your urls. Only routing defines your url's. Therefore, there is no reason whatsoever to sacrifice code clarity and organization for the sake of a particular url scheme.
Furthermore, in most ASP.Net MVC applications I've seen, the controllers are already unwieldy, and combining them all into a single controller would increase the disorganization exponentially.
Even small sites have a handful or two of controllers. Significant sites have dozens, very large sites could have hundreds. Do you really think it is in any way at all feasible to combine dozens of controllers into a single one?
The beauty of ASP.NET MVC comes from the fact that it makes separation of concerns so simple. Unlike ASP.NET Webforms where each page is essentially the View and the Controller, in ASP.NET MVC you can abstract your model logic into separate concerns or 'feature groups'. It makes sense to have a ProductsController that handles everything to do with Products because then you can isolate each set of related functionality in your application into uniform groups that are independently testable and maintainable.
Having a DoEverythingController fundamentally defeats the reasoning behind MVC because it clumps all of the model logic together into one giant spaghetti bowl of code, as opposed to keeping it neat and organized. Furthermore, having a Controller that does everything is not especially object-oriented and resembles a more procedural approach to development like many (older) PHP websites which have some central "functions.php" or similar that does everything. It's messy and disorganized.
In regards to your final point, the routing engine in MVC allows you to construct your routes to given controller actions however you want. The About() action of ControllerX and the Contact() action of ControllerY can both have root URLs like /about and /contact so long as you define the routes accordingly.
Edit (too long for comment)
Generally speaking, the controller classes will be pretty thin as far as code and logic is concerned. Well designed controllers will often hand off more complex operations like retrieving data from the data store to some kind of service so that the surface area for failure remains small. Despite the 'thinness' of most controllers, the larger your site is, the more operations will need to occur and the bulkier your universal controller is going to become. Even in non-MVC scenarios, huge code files suck to maintain and update (like "functions.php" above, for example).
If the site you're developing with MVC is small and limited to only a few more-or-less static pages, then using a single controller for all of them might be a reasonable approach, but if you are constructing a scalable application that will change over time it would be truly defeatist to forgo the use of multiple controllers.
Is like to have all files in the same directory or keep files separated in different folders.
Keeping the application organized in separate controller help in many cases:
1) memory performances
Different from Java Servlet where the controller is shared betwen many request, in asp net mvc the controller is created for each request.
Each time the user make a request, the application need to create the controller.
Think at performances comparison betwen create in memory an instance of a fatcontroller of 100k VS one instance of a light controller of 1k.
2) OO benefit
Controllers are classes. Each time you create a new controller you extend the base controller.
In a complex application you can create yours own controrres (can be more than one) and extend the more appropriated.
For example you can create a controller for "products" and extend from it to create a controller for "vegetables products" and so on..
3) Security.
Suppose that in your application you have a page that execute the CRUD actions on a given item of your db:
- display
- edit
- update
- delete
You want to make this page reserved for registered user only.
If you put all this method in one separate controller you can put the annotation [Authorize] on the controller and by default all the methods inside the controller will be protected.
If you put all the application in one fat controller you have to be careful to place the [Authorize] on each method (what happe if you forgive to put the annotation on the delete method?)
[Authorize]
public class ProductController
public ActionResult Index(String id) {
...
}
public ActionResult Update(String id) {
...
}
public ActionResult Delete(String id) {
...
}
4) Security again.
Suppose you write a classic CRUD (Create Read Update Delete).
Now you want to delete the whole CRUD.
If you keep code separate in different controller you simply delete the controller that belog the CRUD.
If you keep all together in a fatcontroller you have to search for the methods that belog to the CRUD in the whole code.
Again: what hapen if you forget to delete the Delete method?
5) practicality
If you put all together you will have methods like this:
product_edit
product_delete
product_rate
product_create
category_edit
category_delete
category_create
If you organize code in separate controller you will have
product
edit
delte
create
rate
category
edit
delete
create
This is good for many reason: want to modify product in item? simply refactor and rename the productController in itemController.
chaiguy
i think this topic has the potential to illustrate (from the answers) the true benefits of using the controllers to do their own 'lightweight' tasks. one of the many benefits that immediately spring to mind is the fact that each controller can have pretty much the 'same' named actions irrespective of the task at hand (create, edit, delete, list etc).
couple this with a good repository pattern for the data access and some nifty T4 templates and you more or less get an easily understood 'plumbing' job created for free.
this is what makes mvc a pure joy for me - the discreet segmentation of related operations into a unified structure. as previously mentioned, what could become unweildy and cumbersome is instead rendered (no pun intended!!) familiar and focussed.
I guess if you like spaghetti, you would only have one controller.
Complexity, complexity, complexity, that is the question. Software is all about breaking a problem down into manageable units.
Hence multiple controllers.

Building a complex page in asp.net MVC

I am currently considering the best way of building a relatively complex page in asp.net mvc. The page (and pages like it) will contain numerous 'controls' such as a shopping basket, recent news widget, login controls and more. In other words, it will be very component based.
My question is, what is the best way of building something like this in asp.net MVC? In regular webforms the answer would be simple thanks to user controls and the fact they can be nicely self contained. In MVC, I understand that in theory I should probably build a viewmodel that includes all the data needed for all my widgets and then render partial views in whatever page I'm building.
Could an alternative approach be to use javascript to load widgets 'dynamically' (think jQuery load) by simply calling into controllers that render partial views. That way I could have a basket controller, which when called renders out a basket. Of course, this relies on javascript....
Whats the best practise for situations like this?
Thanks
You could of course use JavaScript to populate the page sections but then this content will not be accessible to search engines (but that probably does not concern you).
What you need to understand that there is currently no way to make these partial views perform independently. Like talking to their own controller and posting data while having the rest of the stay unchanged (like it could have been done with WebForms and user controls). If you think postbacks and control state these things do not exist any longer. Your "control" makes a post, the controller has to process the request and then recreate the complete view along with all element values, states and other "user controls".
Unless you do it asynchronously with JavaScript of course. But then it's not gonna be an accessible page any more.
You can try SubControllers from MvcContrib or Steve Sanderson`s "Partial Request" approach.
But i warn you - communication between (partial requests, i haven't tried subcontrollers myself) them might get tricky and lead to mega failure. Use them only if you are completely sure that they are completely independent.
Anyway - that's a bad idea and should be avoided through controller/viewmodel inheritance or something....
My understanding of MVC is not yet up with WebForms, however is the generally accepted approach for stuff like this to simply throw these things in the ViewBag rather than include them in the ViewModel?
You could send down a main view model with some simple checks on it. Then render the appropriate Action if required. Then each partial could use it's own viewmodel and you wouldn't need to send everything down initially on the same viewmodel.
Razor:
#if (model.ShowShoppingCart)
{
#Html.Action("Index","ShoppingCart")
}
#if (model.blah)
{
#Html.Action("Index","blah")
}

Resources