I'm creating a new ASP.NET MVC application. So far I've used the Account controller for actions related to a user's account -- Login/Logout, Activation (like Register, but I use Register for other actions in the site so I've renamed it), Add/Update Contact information. Up to now, though, I've been concentrating on the administrative user views.
I'm at the point where I'm going to start creating the various views that non-administrative users will see. These are rather limited compared to the administrative interface. My inclination is to create a new set of views and associated controller in the User "family" instead of using the Account views/controller. Is this a good idea or should I stick with the Account controller? My feeling is that since this is for ordinary users it should be a separate controller since Account would apply to both ordinary and administrative users.
EDIT: After reading the first couple of responses, my refactored question is:
Do you consider the Account controller to be for administrative actions related to the user's account or for all actions on the user's account? Would you distinguish between membership/role related views/data and application related views/data to the extent of creating a new controller.
Related, but doesn't directly answer my question: ASP.NET MVC Account Controller usage guidelines?
I don't think there's a right or wrong answer here, so I'll give you my opinion.
Technically, either solution (extending the Account controller or creating a new controller) will work just fine.
So I think this is more a question of how the users perceive the functionality. I think it's a good idea to follow the convention that the URI dictates the controller (or vice versa, if you prefer).
If, for example, you'd like to have the "administrative" actions on a separate path, then that should be a separate controller. You might want to do this, for example, if you use an IIS module for authentication or if it makes your log analysis easier.
On the other hand, it might be the case that the users perceive account functions and administrative functions as part of the same family of actions, except that some users have additional features. If so, then that suggests that should be on the same path in the URI and, hence, part of the same controller.
Summing up, I think this is a question you should ask your user representative instead of folks on this site. :)
Update: Regarding your updated question, I would say that it is fairly natural to put an action for changing a user's password on the Account controller, and that action could be invoked by the user herself, not just an administrator. So I wouldn't presume that the Account controller is strictly for administrative tasks. On the other hand, your example of the fund-raising performance is well outside of the scope of membership-related things, so it is not clear that it belongs on Account, either. I'm still leaning towards, "ask your user representative."
In ASP.NET MVC you will usually create controls based on data types rather than access types. For example:
Instead of 2 /Controllers/UsersControl.cs and /Controllers/Admin/UsersControls.cs it is easier to use one common controller for both admins and regular users - /Controllers/UsersController.cs (by setting different [Authorize] attributes and views).
I would keep existing AccountController.cs for encapsulating account related functionality. And just add new UsersController.cs for the rest Users related functionality (which could have methods like OnlineUsers etc.)
Related
I am hoping to create some secure areas of my MVC application, I understand how users can register, login etc with the out of the box views controllers etc.
One thing that seems to be lost on me is a way to manage these users after they register. Some things I would like to be able to do:
Assign roles to users
C-R-U-D users
C-R-U-D roles
Is this all functionality I have to build myself or am I just missing something here? Everything I have found lends itself to writing code to do all these things, but it seems as though these are standard enough that they should exist.
it's very simple. if you take a look at your auto-generated DB for users, you will see that it already contains tables for roles etc. so everything was already prepared for generic use, you just need to define the basics and use it.
You can first try to play with it a bit by adding values manually to the DB tables, just to get the feel of how it works.
define a role
assign users with that role
now depending on your use, whether you'd like to allow\block access to action or entire controllers just set this for example above a action or class [Authorize(Roles = "Admin")].
in addition to (3) you can also make decisions in the server side (C# and cshtml) according to the user roles, by using:
var userManager = new UserManager(userStore);
if(userManager.IsInRole(user.Id, "Admin")){...}
read more in this link, it goes over the CRUD actions - define and use.
we're stuck. We're puzzling about how to best handle this problem. What would be 'best practice'?
What we need is a push in the right direction. What we want/need is to have different user logins for different MVC areas. And it should (preferably) be possible to be logged in with different users to different areas at the same time. One area is the back office / CMS area, only accessible by admin's, editors, developers, etc. has it's own user database. The other area is a 'website' that is running on it, using an anonymous user (or the currently logged in content editor user) to fetch content from the back office area's REST webservices. This area also has it's own database of users, different roles, that database could be on the other side of the world (figuratively speaking). The [Authorize] attribute will not help much I guess. Or well, we're thinking of creating a special Authorize attribute for the content editor area. In our search for a solution or products solving a similar problem we found that Umbraco is using an UmbracoAuthorizeAttribute to do this.
But this would not solve the problem of supporting 2 login pages and being redirected to area's login page when someone is not logged in to that area. Or how should we handle that?
Is there anyone that could give us a push into the right direction and also tell us what we should think about/be careful with when implementing it? We don't 'need' a complete solution.
[Edit]
Could using Claims be a solution to our predicament? Would that be the right thing to do?
[Edit2]
Also the website area and content editor area should act as two different websites as much as possible. The content editor is allowed having to jump through loops, duck and dive. The website should be able to use whatever authorization mechanizm that is available.
Thank you
The [Authorize] attribute will work for you just fine. However, you will need to assign roles to your users and then apply the [Authorize(Roles="Rolename")] attribute to the controllers for those areas.
For instance, you may have an Admin area, and in Admin you have a UsersController that is used to manage users. You would apply [Authorize(Roles="Admin")] to your UsersController class (and any other controllers in the Admin area).
Next, you neeed to assign roles to users, so that users with those roles can access those areas. How you do that, depends on what kind of authentication you're using. If you're using Windows Authentication, then you need to give them a security group by that name. If you're using Identity or Membership, then you need to enable the proper role management functionality and add the user to the role using the appropriate api when you register the user (and add management functionality to the admin tools).
In this way, a user can be assigned multiple roles, and they can be given access to whatever areas based on the role(s) you give them.
As for why you think it won't work for your other situation, i'm unsure. It sounds like you have two different authentication mechanisms, which is fine as long as they both create standard GenericPrincipals and Identities.
In my opinion, people are way too quick to jump to the "Custom Authorization Attribute" approach, when it's really the wrong thing to do. The standard Authorization Attribute is very flexible because it works with the generic IPrincipal/IIdentity and any authentication that can create those objects will work with it, without changing the attribute.
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 a bit new to ASP.NET MVC and I have a bit of an ordeal. I am developing a website with several roles in it and of course the logic and gui that the user gets depends on the role (duh).
There are 10 separate roles in this application. They do share most of the same functionality but some screens will be different depending on which roles they are in.
Heres my question. All examples and tutorials I've read on the internet and the Apress book that I have been reading show an example how to implement roles with one role (Admin) in which the common way is to provide an Admin Controller (or even Admin area) for the authorized section of the site. However, what if there are 10 roles? Do I really need to code up 10 separate controllers?
Let me help the question by giving detail what is being developed. There will be a menu and the menu items will be filtered by role of what views(or pages) they can and cannot get.
The from what they select, it will provide them a restricted view(or authorized page) which from within will provide a plethora of functionality limited to just that role.
I know there are several different ways to do this, I just want to know what is the recommended or "clean" way.
Have any of you been in this situation and if so, how did you organize the logic for multiple roles? Separate all roles to separate controllers? Have few controllers but just apply authorize filtering on the action methods? Apply the role filtering within the views or partial views and leave the controllers alone?
Unfortunately there are little resources for how to implement several roles out there, I just want to know how to do it the "correct" way in terms of separating the logic.
I would put the pieces of functionality into partial views. Have one controller per piece of website and load partial views based on the role and what should be exposed.
I would only stray from that if you have an excessive amount of differences, like an administrator would possible have. Then I typically make an area to encapsulate that functionality.
Regardless of the controller separation I would definitely use partial views to minimize duplication of similar code. You will reap the benefits when you need to maintain that code.
Use Authorize on the action methods and apply the roles allowed for the operation.
Depending on what's appropriate for the scenario, build a list of available actions from the controller and send that to the view as part of the view model. In some cases its more appropriate to send a simpler view model that tells the view whether each operation is allowed i.e. CanDelete, CanEdit, CanViewDetailedInfo etc.
I'd start with that, and depending on the actual complexity re-factor to any combination of:
An ActionFilter that populates the available actions / instead of explicitly doing it in the controller
Use reflector to look for the list of roles applied in authorize / so you only specify roles once
Your own html helpers that take authorization into account. So when you declare an action link, its only output when the action is supported.
I'm just starting to sketch up the base of a web-based system, and I would like the admin to have the possibility to limit access either by Controller or by Model. My problem is, I can't decide which one (or both?) of them I should go with. Any ideas? Pros/Cons?
First I was leaning towards doing it in the Controllers, seeing as they "control" the flow of the system. But then, thinking that the access should probably be limited by the data it accesses, not the logical part of the system, I felt like I really should go with the Model.
Now I just can't decide.. I've been bouncing back and forth for a couple of days now without actually moving forward at all, so now I turn to You, oh Great Internet, in hope for answers!
My implementation is in C# / ASP.NET / MVC2, but I'm still working "theoretically" so it's not really framework specific..
Although there could be exceptions to this, access control should be done by the controller.
The models should not be holding any procedural functionality, just business logic. Business logic on itself should not need to be access-controlled.
The controller, which contains actions that 'interact' with this business logic and models, should be the place to have access control in. Some frameworks already provide functionality for access control, that can evaluate the state of an application to decide whether a certain action can be performed.
Example:
On a web application, Model "Person" holds "persons", and has a function 'createNew (name)'
Controller 'PersonsController' has action 'addNewPerson()', which reads the name from HTTP Post and calls the function mentioned above. It also has an access rule that says that action 'addNewPerson' may not be called if the current state of the application indicates that the user requesting the action is not logged in.
User authorization is a strictly session-based concern, so that is best dealt with in the Controller. Making Models session-aware is possible, but is a violation of concerns and definitely not easy in my experience. You also have to worry about the requests being thread-safe depending on your technology stack.
The way Rails apps typically deal with this is by adding authorization functions to the Controller base class, and letting you define a before_filter to either the entire controller or the specific actions which need to authorize the request.
Typically, I would expect your users to have roles that have access to a a range of functions they can perform on a range of models. This access/no access lookup would be made in the controller.
In the current project I'm working on, we limit access at the controller level via action filters.
The action filters can be defined for a specific action if we want to limit access just to that specifically (ex. a certain page the user shouldn't see) or defined on the controller if that entire area is limited.
The action filter itself is pretty simple, and uses the HttpContext to find the user's identity, but in our case we're using form's authentication so this may differ based on what type of authentication mechanism you're using.