asp.net MVC3 razor: display actionlink based on user role

C#asp.net Mvc-3Razor

C# Problem Overview


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();
}

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

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

Solution 3 - C#

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;
        }

Solution 4 - C#

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.

Solution 5 - C#

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>
}

Solution 6 - C#

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" })

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMathias NohallView Question on Stackoverflow
Solution 1 - C#RichardView Answer on Stackoverflow
Solution 2 - C#MatthieuView Answer on Stackoverflow
Solution 3 - C#Elan HassonView Answer on Stackoverflow
Solution 4 - C#Sudarshan_SMDView Answer on Stackoverflow
Solution 5 - C#OlekView Answer on Stackoverflow
Solution 6 - C#Paolo The Caveman RussoView Answer on Stackoverflow