views:

556

answers:

4

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?

+1  A: 

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]

Marc Gravell
I guess my confusion / frustration with the pattern really starts to build when talking about a typical scenario where one might have nested folders to segregate functionality. For example, a products controller for users, but then an Admin->Products controller for maintaining products. Where? How?
Chris
+1  A: 

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.

Troy
I get that, but what about views? In the scenario I described, I might want the controller actions for the admin section to inherit a separate master page than those for the user section. There doesn't seem to be a good logical way to isolate the views in this way based on the master page they use.
Chris
controller actions = views, I mean
Chris
You could have an Admin masterpage in the Views/Admin folder that the views in Views/Report reference. I don't see anything wrong with doing that - you're really talking about presentation templates here, nothing the controller should know about.
Troy
+2  A: 

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.

J Wynia
+2  A: 

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.

Mehrdad Afshari
This is probably the best idea. I can see designing the user portion of the site to use the MVC stuff while keeping the admin specific logic in regular web forms. Thanks for reminding me.
Chris