Reputation: 2955
I have a view to display a list of items. The user can edit, delete or create new items, but according to their authorizations they may or may not be allowed to do some of this actions.
I have the requirement to display only the actions which the current user is allowed to do, but I don't want to clutter the views with authorization if-else's
Despise of being a very common requirement, I can't find a real satisfactory way of doing it.
My best approach so far is to provide an overload to the Html.ActionLink
extension method that takes the permission to ask for, but there are going to be more complex scenarios, like hiding entire blocks of html or switching a textbox for a label+hidden.
Is there a better way to do this?
Upvotes: 5
Views: 573
Reputation: 1379
I personally don't see anything wrong with this kind of conditional logic within the view. The logic is still all about presentation. You decide whether to show or hide, enable or disable, highlight etc. This is the view's job, not the controller's. As long as the view does not need to actually compute anything to come to its decision. The controller should be agnostic of the view's implementation as much as the other way around.
My approach would be this:
This also has the benefit that the view itself can be removed and replaced without any effect on the controller.
Upvotes: 1
Reputation: 1979
In complicated situations where are many conditions and rules I'm doing this that way:
ViewModel
public class ModelView
{
private IAuthorisationService { get; set; }
public bool CanShow
{
...
}
}
View:
<% if(Model.CanShow) { %>
<html>
<% } %>
Upvotes: 0
Reputation: 806
Would it not be simpler to create several views with various controls based on what values the user can change, then return the right view based on the user's access rights?
Views should be for presenting information only, there really shouldn't be any conditional logic contained in them, or at least a bare minimum.
I've always found when i get to the point where i'm finding it hard to grok a situation like yours, the best solution is always to go back to the controller and e-assess what i'm passing to the view in the first place.
By the time the View is called to do its job, all of the important 'decisions' should have already been made.
Upvotes: 0
Reputation: 41236
One example I can think of would be to invoke Html.RenderAction (link: http://msdn.microsoft.com/en-us/library/ee703490.aspx), and then pass the link you wish to use as a route value to the action method (it will appear as a parameter on your action). Because it's a RenderAction, you get to go back through the controller process and thus you can have it render whatever view or data you want depending on the user's state.
Example:
<% Html.RenderAction("Permissions" /* Controller */, "PermissionLink", new { Url = "Admin.aspx" }); %>
And your controller would have something like:
public ActionResult PermissionsLink (string url)
{
// Do Whatever kind of Authentication you want here, Session is available, etc
if(authenticated)
return View("Link");
else
return View("Blank");
}
Upvotes: 2
Reputation: 8304
We had this same issue. We ended up writing a lot of helper methods and in cases where lots of html output was required, we put them in partial views.
Upvotes: 0