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!
Related
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'm building a site in ASP.NET MVC 2 that will allow for anonymous users and registered users. When a user is logged in, I want to display multiple pieces of information related to that profile on every page (i.e. hometown, favorite color, etc.). From a view perspective, I understand using Master pages and creating partials to keep it DRY.
However, where I am getting stuck is how do I pass this user information to the view for every page? I already have the relationships between database tables established (I'm using EF), so I can do this on an individual basis for each action through ViewData, but that's obviously ridiculous for every page on the site.
So far, my research has started to lead me down the path of creating a base controller and base view model that the other controllers and view models will inherit from. But I feel like I'm missing something obvious. Any pointers?
If you have your Master page use the RenderAction method, it can invoke controller actions for the various repetitive parts of your page, each of which can perform data access and render a partial view. That allows you to separate your view models while still displaying certain elements on all your pages.
This approach works great for us.
We use a base controller to store it in ViewData.
You could also use an action attribute on the controller rather than inheriting from a base controller.
You could create a base class for your models that contains the data that is display on every page.
I'm still just getting into MVC, and for my first real project I plan on creating a blog. This will be extremely basic (at least at first). Everything I need is going to be on the same page. Here are the initial features I am shooting for:
User should be able to log in, but not register (I will be the only one able to post, and I added myself directly to the DB.
Blog posts should be listed in descending order with a Title, a post date, and the body. No comments required for now.
The bottom of the page will always have an area to make a new post, assuming you're logged in.
Since I'm still new to the MVC structure, I'd like some advice on how it should be organized.
For my models, I figured I should have a post repository and a BlogPost class for the post data which can be used for both the posting and retrieving. I would also need a class for the user.
When it comes to controllers I'm a bit less confident. Should I have a different controller for every type of action? For example, posting should have a controller, retrieving should have a controller, logging in should have a controller, etc?
As for the views, since I really only need a single page, should I only have a single view and have that view output the appropriate content from my controllers?
Just let me know if I'm on the right track, I suppose. If my thought process is way off, please tell me. I've just started working my way through Steven Sanderson's MVC 2 book, but I feel like I need to go out on my own and play between my reading sessions.
Thanks.
Controllers should be grouped by functionality. You could also have a controller per resource (REST). You could have an AuthenticationController which handles authentication and PostsController which will handle the posts retrieval and adding a new post. As far as the views are concerned assuming you will have a single page that will list posts and add new posts you could have a single view but maybe with multiple partial views/editor/display templates.
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.
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]