I've got an ASP.NET MVC 3 site with an admin panel (don't we all? :) - I've used my own solution for a very secured login system.
Now, on each view in the admin controller I need to make checks that the user is logged and has the proper authorization, so each time I run the same verification and authorization methods on each view separately.
How could I make the same checks for all the requests to a certain controller? (I mean, right all the checks only once and in one place)
(I also would like to have an exception, so I could allow user to use the login page inside the admin controller and outside of it)
Thanks!
Use an attribute on the controller. Either the standard AuthorizeAttribute (see this) or write your own.
What you're looking for is action filter attributes. They are basically an attribute you can place on a controller that allows you to intercept calls to every action method within a controller and are therefore perfect for security as you can deny/accept requests: http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspx
If you want to limit the entire controller instead of the individual actions you could place the [Authorize] attribute like so:
[Authorize]
public class PageController : Controller
{ ... }
Related
I'm trying to come up with a way to cache the actions in a controller only for anonymous users using the [OutputCache(Duration = 3600] annotation. E.g.:
[OutputCache(Duration = 3600)]
[ActionName("Test")]
public async Task<ViewResult> Test() {...}
In my research I came across a very clever way to use ActionMethodSelectionAttribute for exactly this, but as soon as the anonymous action is cached it applies for both the anonymous and authorized version.
I need this caching for the front page and for information pages. In all cases the top menu will be different for authorized users. The problem is that the menu is a partial added in the _Layout and so cached together with the rest of the action. E.g:
<body>
<div class="contain-to-grid oversizedContainer">
#Html.Action("Menu", "Framework")
</div>
#RenderBody()
The second problem is that on the information pages some of what is displayed will depend on if the user is autherized (checked using razor #if !Request.IsAuthenticated) and data in the view model (#Model).
I'd prefer something that would not require me to rewrite all my views.
PS! I'm aware of VaryByParam, but the actions do not take any parameters and are linked to directly.
I have created a partial view and I am using it in admin controller's Home action method. Inside partial view, I have an Account Controller with action method named Logon. I am trying to access main view's URL like this
if (Url.ToString().ToLower().Contains("/admin"))
return Redirect("/Admin/Index");
but I cant get the required result. How to get it admin/home ?
From the comments above it looks like you want to just access the current url. If so, then you can simply use the Request object. E.g.
Request.Url.AbsoluteUri
I wonder why you need this though... what is it you are trying to do exactly?
I'm using ASP.NET MVC 3.
I would like to create an action filter to determine if a user can access a view. I have a User class with properties like IsAdministrator, IsTrusteeUser and IsAuditUser. How would I create an action filter to block certain users if the don't belong in some of these roles?
And aslo how would I use this in my views to hide/display certain controls? I would appreciated some code :)
Why re-invent the wheel?
Put the [Authorize] action filter on the action/controller, specifying the role required:
[Authorize(Roles = "Administrator")]
public ActionResult SomeAdminPage() { // }
Either that, or you could implement your own custom authorization filter by implementing IAuthorizationFilter.
You can implement IActionFilter interface for writing such an attribute extension for Users access permissions checking, a little about coding you can find on
here
To hide/display certain controls on UI, it is not the work of ActionFilters, rather you should either make separate views for each user and redirect him accordingly or do some
If/else
to acheive this.
I am trying to figure out where the appropriate place is to intercept the resolution of what view + controller is being called in ASP.Net MVC 2. I have a situation where I have a controller and a corresponding set of views. I also have the possibility of a customized version of both the controller and N of the views sitting in the project (or we may use something like Portable Views from the MvcContrib project). If the customized version of the controller or view(s) exists at run time, and the user satisfies certain criteria, I need to call the customized controller and use the appropriate customized view. At design/compile time we don't know what customizations may be in place.
My first run at this was by using a custom controller factory that returns a custom controller if it exists. However, this controller is "wired up" to the standard view, and I cannot figure out how to return the customized view if it also exists.
To complicate matters, there may be no customized controller but customized views, and visa-versa.
Sounds like you're on the right track. You've got custom controller selection logic in place, but you need to also have custom View selection logic.
You can override and extend the default ViewEngine to plug into your app that uses your own logic to look for the view locations. Here's a good walkthrough of a simple ViewEngine that does exactly that.
I am working on an ASP.NET MVC application that contains a header and menu on each page. The menu and header are dynamic. In other words, the menu items and header information are determined at runtime.
My initial thought is to build a base Controller from which all other controllers derive. In the base controller, I will obtain the menu and header data and insert the required information into the ViewData. Finally, I will use a ViewUserControl to display the header and menu through a master page template.
So, I'm trying to determine the best practice for building such functionality. Also, if this is the recommended approach, which method should I override (I'm guessing Execute) when obtaining the data for insertion into the ViewData.
I'm sure this is a common scenario, so any advice/best-practices would be appreciated! Thanks in advance!
EDIT:
I did find the following resources after posting this (of course), but any additional anecdotes would be awesome!
http://www.singingeels.com/Blogs/Nullable/2008/08/14/How_to_Handle_Side_Content_in_ASPNET_MVC.aspx
How do you use usercontrols in asp.net mvc that display an "island" of data?
Depends on where your information is coming from. We have standard view data that we use to generate some of the information we have on screen that we create in just this fashion. It works well and is easily maintained. We override the View method to implement strongly typed view names and use this information to retrieve some of the data that the master page requires as well.
You could write a helper extension to render the header/menu
That way you could have it show in different places in the view should you need to, but only one place for maintenance.
public static HtmlString MainMenu(this HtmlHelper helper)
Use a base controller class to implement generell filter methods. The controller class implements some filter interfaces IActionFilter, IAuthorizationFilter, IExceptionFilter and IResultFilter which are usefull to implement some common behavior for all controllers.
If the menu data is the same on all pages but different for each unique user.
Generate the menudata in an OnAuthorization or Initialize method of your controller base class. First will be called on authorization. Initialize will be called before every action method. You have access to ViewData Context. Generate the menudata there.
Put the view content for menu and header into the master page and access generated ViewData there.
I tackled a similar design challenge a couple months ago - implementing a breadcrumb feature that changes as user navigates from page to page.
I overrided the OnActionExecuting method to gather the breadcrumbs and store them in ViewData (I use the name of the action as the breadCrumb of the view). Then I updated the Master page to include a user control that takes the ViewData and renders the breadcrumbs.
One thing to be aware is that if you were using the default ASP.NET MVC error handling attribute [HandleError] and your error page is using the same Master page that attempts to read the ViewData, you will soon find out that you can't access ViewData from your error page and it will raise an exception. Depending on whether you need the ViewData for failure scenarios, the viable solution is to use a separate Master page or do this: How do I pass ViewData to a HandleError View?
I'll answer your question with another question. Will the base controller have to determine what type it really is in order to generate the proper menu data? If so, then you're defeating the purpose of polymorphism and the code to generate the data should go in each controller, perhaps in OnActionExecuting if the menu is the same for all actions. Pushing it back down into a parent class seems likely to end up with some switch statement in the parent class doing what each derived controller really ought to take care of.