63
votes

I'm new to MVC. I want to be able to hide some actionlinks for some users. Say I have a "create" actionlink which I only want administrators to see and click. I want to use some sort of "loggedintemplate" available in asp.net, but it doesn't seem to work in razor.

I could use some sort of code block with an if statement checking the current user and her role, however that may not be best practice?

my index.cshtml..

// want some adminauth attribute here...
@Html.ActionLink("Create New", "Create")

my controller..

// GET: /Speaker/Create
[Authorize(Roles = "Administrators")]
public ActionResult Create()
{
    return View();
}
6

6 Answers

137
votes

I have in the past created a helper function to only return output when a criteria is met like this:

public static MvcHtmlString If(this MvcHtmlString value, bool evaluation)
{
     return evaluation ? value : MvcHtmlString.Empty;
}

so you can use this:

@Html.ActionLink("Create New", "Create").If(User.IsInRole("Administrators"))

This way it is legible and short

42
votes

If you want a code block, that would do in the view :

@if (Roles.IsUserInRole("Administrators"))
{
  <li>@Html.ActionLink("Create New", "Create")</li>
}
7
votes

I've modified Richard's code to provide an optional MvcHtmlString parameter to return if the evaluation is false.

public static MvcHtmlString If(this MvcHtmlString value, bool evaluation, MvcHtmlString falseValue = default(MvcHtmlString))
        {
            return evaluation ? value : falseValue;
        }
2
votes

If you haven't enabled roleManager and you still want to check User's role, you can do it like this:

 @if (@User.IsInRole("administrator"))
 {
   @Html.ActionLink("Create New Version", "Create")
 }

What we are doing it here is, we are just accessing user's properties. This can useful if you are managing roles yourself.

1
votes

The solution suggested by Richard is really beautiful, though as Matthieu noted someone might need extra html code to be rendered (or not rendered) as well. Thus Matthieu's solution seems to be more widely applicable, I would just centralize the logic regarding which users are considered admins in extension method.

Extension method:

public static bool IsAdmin(this WebViewPage page)
{
    return page.User.IsInRole(@"Domain\ProjectAdmins");
}

Usage:

@if (this.IsAdmin())
{
    <p>
        @Html.ActionLink("Create New Version", "Create")
    </p>
}
0
votes

You can add a function to App_Code/ViewFunctions.cshtml (create if missing)

@using System.Web.Mvc;
@functions{
public static object ConditionalActionLink(object actionLink, ICollection<string> arrAuthUsers)
{
    bool objIsVisible = arrAuthUsers
        .Select(s => User.IsInRole(s))
        .Where(s => s.Equals(true))
        .Any();

    return (objIsVisible)
        ? actionLink
        : MvcHtmlString.Empty;
}

To use that function just add following code to the view.

@ViewFunctions.ConditionalActionLink(
@Html.ActionLink("TextToDisplay", "SomeAction", new { Area = "SomeArea", Controller = "SomeController" }), 
new string[] { "administrator","jDoe", "someOtherUser" })