Implementing RoleManager in ASP.NET MVC 5

2 Comments | Dec 28, 2014

There is something great included in ASP.NET MVC 5 that seems underutilized except by the ASP.NET MVC team. The rest of us seem to be ignoring it, which is apparent when looking at the solutions on StackOverflow (and blogs) for questions like “how do I use roles with ASP.NET MVC 5?” When I look at how identity is implemented in mvc, what stands out is the dependency injection. And, that dependency injection appears to be missing in the answers to how to implement roles. Dependency is a great tool, it’s built into the OWIN implementation, so why not use it?

To implement the role manager in MVC 5, look for a file in App_Start called IdentityConfig.cs. If you don’t have this file, look for the file that contains the implementation of your ApplicationUserManager (derived from UserManager) and ApplicationSignInManager (derived from SignInManager). At the bottom of that file, inside the namespace, add the following class definition:

public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(IRoleStore<IdentityRole, string> store) : base(store)
    {
    }

    public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
    {
        var roleStore = new RoleStore<IdentityRole>(context.Get<AuthenticationDbContext>());
        return new ApplicationRoleManager(roleStore);
    }
}

There are a couple of prototypes for the Create method. In this case, I wanted to get the database context from the OWIN context, so I used the more elaborate overload. If you don’t want to do that, you can use the Create(Func<T>) overload, which doesn’t take any parameters.  Now, to make sure OWIN knows about your ApplicationRoleManager class, go the ConfigureAuth method in your Startup partial class implementation in Startup.Auth.cs (also in App_Start).  Or, you can also put what I’m getting ready to show you in the Configuration method of the OWIN startup class. This class is usually called Startup.cs and you’ll find it in the same directory as the root web.config.

public void ConfigureAuth(IAppBuilder app)
{
   // Configure the db context, user manager and signin manager to use a single instance per request
   app.CreatePerOwinContext(AuthenticationDbContext.Create);
   app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
   app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
   app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
   …
}

See how I just stuck that line for ApplicationRoleManager there next to the other authentication delegate registrations?  Alright, so here comes the cool part…now we can just inject the role manager right into the AccountController or whatever other controller we need.  Check this out…


public AccountController(
    SendMailManager emailManager,
    ApplicationUserManager userManager,
    ApplicationSignInManager signInManager,
    ApplicationRoleManager roleManager)
{
    this.MailManager = emailManager;
    this.RoleManager = roleManager;
    this.SignInManager = signInManager;
    this.UserManager = userManager;
}

As you can see, I have already used the dependency injection to insert my own mail manager. AccountController should already be set up with this kind of structure. If it’s not, though, simply changing your constructor to look like this will cause MVC to inject those dependencies into your controller. Then, all you have to do is create a property to hold that ApplicationRoleManager thing and you’re all set!


private ApplicationRoleManager roleManager;
public ApplicationRoleManager RoleManager
{
    get
    {
        return this.roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
    }
    private set { this.roleManager = value; }
}

What?  What?  Dudes, I kid you not. ApplicationRoleManager is now available to your controller through this.RoleManager. And, get this, you haven’t thwarted the testability of your controller by newing up a role manager, user manager, and context in your controller actions.  What?  What?  Dudes, come on.  Dudes.

Really.

Responsive Inline Elements with Twitter Bootstrap

One Comment | Nov 12, 2013

imageTwitter Boostrap is a responsive css platform created by some dudes affiliated with Twitter and since supported and maintained by an open source following. I absolutely love the new version of this css toolkit. They rebuilt it with a mobile first strategy and it’s very easy to layout pages once you get the hang of it. Using a css / javascript framework like bootstrap is certainly much easier than coding your layout by hand. And, you get a “leg up” when it comes to adding responsive features to your site. Bootstrap includes column layout classes that let you specify size and placement based upon the viewport width. In addition, there are a handful of responsive helpers to hide and show content based upon the user’s device size. Most notably, the visible-xs, visible-sm, visible-md, and visible-lg classes let you show content for devices corresponding to those sizes (they are listed in the bootstrap docs.) hidden-xs, hidden-sm, hidden-md, and hidden-lg let you hide content for devices with those respective sizes.

These helpers work great for showing and hiding block elements. Unfortunately, there isn’t a provision yet in Twitter Bootstrap (as of the time of this writing) for inline elements. We are using the navbar classes to create a navigation bar at the top of our website, www.crowdit.com. When you shrink the width of the screen to tablet or phone size, the tools in the navbar are turned into a drop down menu, and a button appears on the right side of the navbar. This is great! But, we wanted different content to display based upon whether the items were on the navbar versus when they were in the dropdown menu. The visible-?? and hidden-?? classes make this easy for images and block elements. In our case, we wanted our anchors to show different text depending upon whether they’re in the navbar, or in the dropdown. span is inherently inline and it can be a block element.

My first approach was to create two anchors for each option, one set visible when the navbar is on a desktop or laptop with a wide display and another set visible when the elements converted to a dropdown menu. That works fine with the visible-?? and hidden-?? classes, but it just doesn’t seem that clean to me. I put up with that for about a week…last night I created the following classes to augment the block-based classes provided by bootstrap.

.cdt-hidden-xs, .cdt-hidden-sm, .cdt-hidden-md, .cdt-hidden-lg {
    display: inline !important;
}

@media (max-width:767px)
{
    .cdt-hidden-xs, .cdt-hidden-sm.cdt-hidden-xs, .cdt-hidden-md.cdt-hidden-xs, .cdt-hidden-lg.cdt-hidden-xs {
        display: none !important;
    }
}

@media (min-width:768px) and (max-width:991px) {
    .cdt-hidden-xs.cdt-hidden-sm, .cdt-hidden-sm, .cdt-hidden-md.cdt-hidden-sm, .cdt-hidden-lg.cdt-hidden-sm {
        display: none !important;
    }
}

@media (min-width:992px) and (max-width:1199px) {
    .cdt-hidden-xs.cdt-hidden-md, .cdt-hidden-sm.cdt-hidden-md, .cdt-hidden-md, .cdt-hidden-lg.cdt-hidden-md {
        display: none !important;
    }
}

@media (min-width:1200px) {
    .cdt-hidden-xs.cdt-hidden-lg, .cdt-hidden-sm.cdt-hidden-lg, .cdt-hidden-md.cdt-hidden-lg, .cdt-hidden-lg {
        display: none !important;
    }
}

.cdt-visible-xs, .cdt-visible-sm, .cdt-visible-md, .cdt-visible-lg {
    display: none !important;
}

@media (max-width:767px)
{
    .cdt-visible-xs, .cdt-visible-sm.cdt-visible-xs, .cdt-visible-md.cdt-visible-xs, .cdt-visible-lg.cdt-visible-xs {
        display: inline !important;
    }
}

@media (min-width:768px) and (max-width:991px) {
    .cdt-visible-xs.cdt-visible-sm, .cdt-visible-sm, .cdt-visible-md.cdt-visible-sm, .cdt-visible-lg.cdt-visible-sm {
        display: inline !important;
    }
}

@media (min-width:992px) and (max-width:1199px) {
    .cdt-visible-xs.cdt-visible-md, .cdt-visible-sm.cdt-visible-md, .cdt-visible-md, .cdt-visible-lg.cdt-visible-md {
        display: inline !important;
    }
}

@media (min-width:1200px) {
    .cdt-visible-xs.cdt-visible-lg, .cdt-visible-sm.cdt-visible-lg, .cdt-visible-md.cdt-visible-lg, .cdt-visible-lg {
        display: inline !important;
    }
}

I created these by looking at the example provided by bootstrap and consolidating the styles. “cdt” is just a prefix that I’m using to distinguish these classes from the block-based classes in bootstrap. You are welcome to change the prefix to whatever feels right for you. These classes can be applied to spans in textual content to hide and show text based upon the browser width. Applying the styles is simple…

<span class=”cdt-visible-xs”>This text is visible in extra small</span>

<span class=”cdt-visible-sm”>This text is visible in small</span>

Why would you want to do this? Here are a couple of examples, shown in screen shots.

image

This is the CrowdIt navbar on larger displays. Notice how the text is two line and certain words are capitalized? Now, check this out! Here is a screen shot showing the dropdown menu that’s displayed when the browser window is tablet or phone sized. The markup to make this happen is quite simple…take a look.

image

<li>
    <a href="@Url.Action("what-is-crowdit","home")" title="Learn about what CrowdIt can do for your Small Business">
        <span class="cdt-hidden-xs">WHAT<br /><small>is CrowdIt?</small></span>
        <span class="cdt-visible-xs">What is CrowdIt?</span>
    </a>
</li>

There is a single anchor tag in this example and only the spans change visibility based on browser width. I left them separate for readability and because I wanted to use the small tag; however, you could just as easily hide the “WHAT” and the br tag on small displays and replace them with “What “, consolidating this even further to text containing a single span.

<span class=”cdt-hidden-xs”>WHAT<br /></span><span class=”cdt-visible-xs”>What </span>is CrowdIt?

You might be a master of css and have a better method of handling this problem. If so, I’d love to hear about your solution…leave me some feedback! You’ll be entered into a drawing for a chance to win an autographed picture of ME! Yay!

Html.ValidationSummary and Multiple Forms

4 Comments | Nov 11, 2013

The Html.ValidationSummary helper writes a div with a list of general errors added to the model state while a request is being serviced. There is generally one form per view or partial view, I think, so often there is only one call to Html.ValidationSummary in the page resulting from the assembly of your views. And, consequently, there is no problem with the markup that Html.ValidationSummary spits out as a result. What if you want to put multiple forms in one view? Even if you create a view model that’s an aggregate of the view models for each form, the error validation summary is going to contain errors from both forms. Check out this screen shot, which shows a page with multiple forms. Notice how the error validation summary shows up twice. Grrr! Errors for the login form also show up in the registration form.

image

Luckily, there is an easy way around this. Pull the errors out of the model state and separate them for each form. You’ll need to identify the appropriate form by setting the key when you make calls to ModelState.AddModelError. Assume in my example that errors for the login form are added to model state using the “LoginForm” key. And, likewise, assume that errors for the registration form are added to model state using the “RegistrationForm” key. An example of that might look like this…

// If we got this far, something failed, redisplay form
ModelState.AddModelError("LoginForm", "User name or password is not right...");
return View(model);

Over in the code for your View, you can pull each form’s errors from the model state using lambda expressions that look like these…

var LoginFormErrors = ViewData.ModelState.Where(ms => ms.Key == "LoginForm");
var RegistrationFormErrors = ViewData.ModelState.Where(ms => ms.Key == "RegistrationForm");

Now that you have two collections containing errors, you can display only the errors specific to each form. I’m doing that in my code by removing the calls to Html.ValidationSummary and replacing them with enumerators that look like this…

if(LoginFormErrors.Count() > 0)
{
<div class="cdt-error-list">
    <ul>
    @foreach (var entry in LoginFormErrors)
    {
        foreach (var error in entry.Value.Errors)
        {
            <li>@error.ErrorMessage</li>
        }
    }
    </ul>
</div>
}

…and for the registration form, the code looks like this…

@if(RegistrationFormErrors.Count() > 0)
{
<div class="cdt-error-list">
    <ul>
    @foreach (var entry in RegistrationFormErrors)
    {
        foreach (var error in entry.Value.Errors)
        {
            <li>@error.ErrorMessage</li>
        }
    }
    </ul>
</div>
}

The result is a nice clean separation of the list of errors that are specific to each form. And, this is important because each form is submitted separately in my case, so both forms don’t generate errors in the same context. As you’ll see in the screen shot below, errors added to the model state when the login form is submitted do not show up in the registration form’s validation summary.

image