views:

140

answers:

5

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.

+5  A: 

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?

qstarin
+1 for noting that controller actions have nothing to do with urls. I wish more people understood this . . .
Wyatt Barnett
I think, then, my question is what is all this stuff that the controllers are doing? I don't have a real understanding of controllers other than the very simple default examples of taking a request and returning a view.
chaiguy
Controllers do as little as possible. But that's still 5-20 lines of code for each action. And that code often has a couple dependencies (sometimes more, rarely less). So if I have an AccountController, might have 10 views. It's quite common for at least 1 POST to accompany each GET. So now we're up to easily 20 action methods in a single controller, each with a handful of code and a couple dependencies (assuming we follow SRP in our services, often not the case in sample apps). Now, multiply by 10 controllers and we're up to 1000+ lines of code and a few hundred dependencies. That's why.
qstarin
I completely agree with this and @Wyatt above, except that my ideal controller action is 2-5 lines of code.
Ryan
@Ryan: I find 5 lines (much less 2) can be hard to hit with Actions that call into a service (rather than just grab data and display it in a view), though judicious use of action filter attributes helps keep the line count down.
qstarin
@qstarin You're going to love global filters in MVC3.
Ryan
+3  A: 

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.

Nathan Taylor
Concerning your second paragraph, it seems to me the object-oriented logic should be entirely maintained in the models themselves, and this leads to my confusion as to what the controllers are actually for that they need to be object-oriented themselves. Doesn't a controller essentially just map a url/request to some aspect of an object, and could that not be done with very minimal code?
chaiguy
@Chaiguy Edited my response.
Nathan Taylor
Thanks. I'm sure I will come to see this eventually as I learn more, but I guess I'm just experiencing a problem similar to when new users are learning object-oriented programming and don't have that intuition developed about how to separate classes.
chaiguy
The controllers aren't particularly object-oriented. They inherit from a base class, but otherwise they are very straight forward. But despite how simply they can and should be, putting all Actions in an entire web app in a single controller would lead to a fairly ugly, hard-to-maintain class with a whole lot of dependencies.
qstarin
@qstarin I describe the controllers as 'object-oriented' only in that they should focus on a single set of related functionality. Perhaps not the best way to say that, but my point was that heaping a mass of unrelated features together into a giant class amounts to nothing more than headaches.
Nathan Taylor
@Nathan Taylor: I agree with you, was just trying to clarify for chaiguy based on his comment.
qstarin
+1  A: 

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.

jim
+1  A: 

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.

awrigley
+1  A: 

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.

Bugeo