14

I have an Extension Method that verifies if the user is able to see a portion of the webpage, based on a Role.

If I simple remove the content, this brings me more work as all the missing forms will not be correctly registered upon save and I have to deal with this behavior by modifying all my code, so I thought why not just use display:none; attribute?

I would like to have something like:

@using(Html.RoleAccess(currentUser, RoleAccessType.Content_General_Website))
{
    ...
}

and that this would write something like:

<div class="role_Content_General_Website" style="display:none;">
    ...
</div>

or use display:block; if the user has access...

I can create a simple HtmlHelper but how do I write one that also outputs the ending </div>?

public static string RoleAccess(
         this HtmlHelper helper, 
         UserInfo user, 
         RoleAccessType role)
{
   return 
       String.Format(
            "<div class='role_{0}' style='display:{1}'>", 
            role.ToString(), user.HasAccess(role));
}
balexandre
  • 73,608
  • 45
  • 233
  • 342

1 Answers1

22
public static class HtmlExtensions
{
    private class RoleContainer : IDisposable
    {
        private readonly TextWriter _writer;
        public RoleContainer(TextWriter writer)
        {
            _writer = writer;
        }

        public void Dispose()
        {
            _writer.Write("</div>");
        }
    }

    public static IDisposable RoleAccess(this HtmlHelper htmlHelper, string role)
    {
        var user = htmlHelper.ViewContext.HttpContext.User;
        var style = "display:none;";
        if (user.IsInRole(role))
        {
            style = "display:block;";
        }
        var writer = htmlHelper.ViewContext.Writer;
        writer.WriteLine("<div class=\"role_Content_General_Website\" style=\"" + style + "\">");
        return new RoleContainer(writer);
    }
}

and then you can use it like this:

@using(Html.RoleAccess("Administrator"))
{
    ...
}

You could obviously adapt the arguments of the helper to match your requirements:

public static IDisposable RoleAccess(
    this HtmlHelper helper, 
    UserInfo user, 
    RoleAccessType role
)
{
    var style = "display:none;";
    if (user.HasAccess(role))
    {
        style = "display:block;";
    }
    var writer = htmlHelper.ViewContext.Writer;
    writer.WriteLine("<div class=\"role_" + role.ToString() + "\" style=\"" + style + "\">");
    return new RoleContainer(writer);
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • First of all, Merci Darin! I also added an override to append `display:none` when the element is an `
  • ` for example, but doing `return "style='display:none;'";` I'm getting `style='display:none;'` what should I return so my Extension Helper does not need `@Html.Raw(Html.RoleAccess(...)) {}`?
  • – balexandre Nov 28 '11 at 09:28
  • So what if I wanted to nest containers in a "meta container"? I'm stuck on what to return: `// public static IDisposable BeginFieldset(this HtmlHelper htmlHelper, string label, object htmlAttributes = null) { using (htmlHelper.BeginClosableTag("div", attr)) { using (htmlHelper.BeginClosableTag("fieldset", null)) { var legend = new TagBuilder("legend"); //... var writer = htmlHelper.ViewContext.Writer; writer.WriteLine(legend.ToString()); return new ClosableTag(writer, ""); } } }` where `ClosableTag` is like `RoleContainer`. – drzaus Jun 13 '12 at 21:25