I am always trumped by this question when starting a new project. When I look at examples like Mephisto, Typo, etc. they route their root to a controller that relates to a specific resource/model.
My problem is, almost every website I've ever built, I feel like my front page is actually a collaboration of all my models, and I can't see myself pointing to a controller that is related to a specific one as my landing page.
Does anyone tend to create a controller that is specifically intended for the front of the website? Or if maybe I am looking at this entirely wrong, please let me know.
edit:
Here is where my confusion exists:
rboard's routes maps root to a controller named index... but i can't even find an index controller
mephisto's routes use some custom routing thing, and there is no root or even a map.connect to '/'
radiant's routes for the bulk of the app goes to one controller, which then does some crazy magic
track's routes go to a controller that is related to a resource (this is an example closest to what i described above)... but doesnt fit me because as i said, my roots tend to have tons of things.
spot us actually does something similar to what i do, have a home controller that just has a show actions, and that is my front page.
My problem is, almost every website
I've ever built, I feel like my front
page is actually a collaboration of
all my models, and I can't see myself
pointing to a controller that is
related to a specific one as my
landing page.
Exactly. So what you're doing is correct.
I often make two controllers for interactions with things that aren't the usual REST stuff: 'welcome' and 'dashboard.' The welcome controller is mapped to my site's root, and the 'dashboard' controller is similar, but for logged in users.
Does anyone tend to create a controller that is specifically intended for the front of the website? Or if maybe I am looking at this entirely wrong, please let me know.
The short answer is "yes".
For what it's worth, I usually take a similar approach to Spot.Us and define a HomeController with an index action/view and just leave it at that.
Not sure if this is the answer you're looking for, but here's what I do. I usually use a combination of two controller types, a Front Controller and Action controllers. The Front Controller takes care of URL routing and determining what action to take, while the Action Controllers provide the actual functionality. It's a similar approach to what Zend Framework does.
With that being said, I'll pipe all traffic through a Front Controller, including front page traffic. I usually have an action controller named "IndexController" that handles miscellaneous page requests, and often the front page falls under that category (as well as things like privacy policy pages, contact forms, etc).
If a page is not specifically related to any of the business domain logic of the site, I tend to put it under my Index action controller, although I strive to group site functionality as best as possible.
SiteController seems like the best name to me. SiteController will contain your most important action, index, and my SiteController always contains other actions like contact, about, etc.
Related
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.
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 .
I am kinda of confused on when I should be making a new controller it seems like every time I make a button that goes somewhere I would need to make a new controller to get the right pathing names.
For instance in this scenario I have a signIn controller.
this controller would have
1. Login view
2. RestPassword view
3. CreateAccount view
So if they click login they go to some other controller(lets call it AccountController) so this will have all the account view and stuff in it.
Now how about the RestPassword view? When it rests the user password I want it to go to a page that shows them that it was a success(most sites seem to do this for example asp.net site if you enter in a email address it will go to another page and tell you that the new password has been sent).
So now what should it be another view? a controller?
If it is a view then the pathing would look like
http://www.site.com/signIn/EmailForgottenPassword
what kind of looks weird to me.
If I make a new controller then I could have
http://www.site.com/EmailForgottenPassword
What looks alot better to me but this controller would have one just one view in it.
Another example would be on this sigIn page their is a Create Account button. Now when clicked this goes to another page that has a list of different accounts.
Should this also be a new controller? When the accounts are listed on this new page they all link to a Registration Controller with many views in it.
so it would be like SignController -> RegistrationController -> RegistrationController.
this would probably get some nice links.
So like I said it seems like to get nice links that make sense you need to constantly make new controller after controller.
So I must be missing something.
The truth is you never actually need more than one controller. Separate controllers are just ways of separating your concerns. In other words, OO design paradigms impel us to logically divide our code into modules, but you don't have to - everything can be in one controller.
What you do need is a separate controller action for each different type of request you want to process. That is, you need a controller method exposed to the routing table that can be called by typing in some URL and/or providing some GET or POST data. This method then decides what to show the user (the view).
Also, you can have any URL you want point to any controller or controller action you want by modifying the routing table in Globals.asax.
You probably have more specific questions about my answer - please post them and I will edit them in.
In your specific case you one controller would suffice. I would name it the AccountController and add the following actions to it.
Login
Logout
Create
CreateConfirmation
ResetPassword
ResetPasswordConfirmation
then for the ones you want to have confirmation screens you can use the the Post Redirect Get (PRG) pattern.
as to the naming. In general you want to use noun for a controller and verbs for actions on those controllers. That way you get nice readable URL's that make sense. And for the noun you can pick the logical/business term (better then the technical term) that the controller deals with. So accounts, customers, products, blogpost etc...
If you are following SOLID principles then you should name them very specifically. If you are using ASP.NET MVC 2 then I would put major widgets into "areas" and then give controllers good names. Make your URLs happy!
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]
So I am in a situation where I have to decide whether or not to have a separate controller for a particular piece of code. We have a home page that acts like a hub for the rest of the site. The page is accessible to all users (logged in as well as non-logged-in). I was thinking about having home as a separate controller and an action called index. Thinking about this situation, I started wondering if there are any rules or guidelines on this front.
My perception has been that if a code revolves around an entity, separation is needed. (Similar to REST guidelines) If the entity is a noun, it should be a controller. If the entity is a verb, it should probably be an action and should reside in the controller whose name is the same as that of the noun that the verb refers to. Some colleagues suggested that since this is one action, it should reside in the some existing controller and should be named home. I strongly disagreed, however, I could not find a trusted source that would back me up on this.
Would like to know your thoughts.
In this case I have to agree with your co-workers.
REST is a nice approach to take when dealing with resources, as you say. This allows you to create a consistent interface especially with a view to creating a web service.
However REST doesn't actually map too well to a web browser setting. You'll notice for example that even for resources your /edit and /new actions are just GET requests returning an HTML form pointing to the relevant RESTful action. 'edit' and 'new' aren't RESTy at all.
Similarly, the home page is generally a user-friendly amalgamation of various data, not suited to a RESTful interface. So either just stick an extra controller in with one action, or alternatively use an existing controller's 'list' action as the home page
The problem starts with the phrase
If an entity is a verb
If you are attempting to produce a RESTful architecture, an entity cannot be a verb. The only verbs allowed if you are using HTTP are GET, PUT, POST, DELETE, HEAD, OPTIONS. All entities should be mapped to some noun and if you are trying to retrieve that entity you should be using the verb GET. Personally, I would map that to the method Get() on my controller but I don't know if Rails lets you do that.
The quick (and unhelpful) answer is that either way works fine.
I think that everybody comes across this decision at one point, and the decision you make depends on the likely future of the website... which means it's prone to premature optimisation... but that's always the catch,
As you've probably guessed by now, "home" is in some ways a verb as well as a noun, thus why you're having trouble figuring out what to do.
The answer depends on a combination of interpretation of your website structure and how much time is available to you...
if you have very little time to work on this... then stuffing the 'home' action into another controller is often considered the expedient option. It works, it lets you move onto other (probably more productive) tasks.
However, I agree that sometimes it is good to step back and think about what you're doing and whether it could be done "better"...
in this case, though it's harder to define "better" - as it's unlikely that putting the home action in a new controller would be measurably faster... and if it's the only action int he controller... it's debatable whether it's better, architecturally, to just adding it onto an existing controller...
So we start in on what is mostly a philosophical debate... in other words, no answer will be "more correct" than the other- it's more a matter of taste and circumstance. In this case, the debate hinges on making the structure more RESTful.
To be faithful to RESTful architecture, you would indeed move the action into it's own controller... but you'd first have to identify what the entity is. The "home" page is often not readily identifiable as a specific db entity... it's more often a portal-page.
Sometimes you can pick an entity eg online shops will often have a home page that is actually a "products#index" variation, or sometimes the "home" page is a UserAccount#show page... but more often, your home page will not be simple, and will combine information from multiple entities... thus why it is difficult to decide what the "right" architecture will be.
If you cannot identify a specific entity, then there is a valid debate as to whether to move the action into a specific controller.
however, you can always create a new "entity" that is centred around the architecture of the site. This is especially likely if you are going to come up with other non-entity-specific pages for the site (eg T&Cs or an "about our company" page).
The usual fallback being a "PageController" (or similar name) which isn't linked to an Active Record model, but to a more nebulous entity, in this case a "page" which is recognisable to a user of the website (eg the "home page" and the "T&C page" and the "about page"). Each action would be for a specific page...
So, it's up to you as to whether this fits better with your view of the architecture of your system... and whether it's worth the effort... but that's my view on the debate. :)