TL;DR: If you find yourself in a hurry, and you just want to quickly check how to setup ASP.NET Identity in a MVC project using StructureMap you can just check the example project in github
Although ASP.NET project templates are a very useful way to start a new project, some people don’t feel comfortable using them. There are many reasons for this, some people don’t like the project folder structure, others simply like to create the whole project themselves instead of starting from a sample application.
This was at some point the most requested feature in the ASP.NET MVC3 Uservoice site.
If you do decide to start from an empty project template you’ll have to setup everything yourself. That’s not necessarily a bad thing. It provides you the opportunity to setup the project in whichever way you prefer and you can for example use an IoC container to setup ASP.NET Identity which the focus of this blog post.
The main reason why I decided to write this down was because I’ve heard the way ASP.NET Identity is setup being described as “poor man’s dependency injection”, namely the use of .CreatePerOwinContext<T>
that you’ll find on the one of the partial class files for Startup.cs
in the default template for MVC with Individual User Accounts.
The video where I heard this was ASP.NET Identity Security. The reason why it’s described as “poor man’s DI” is because, instead of actual dependency injection, the dependencies are created in the Startup
class, stored as Owin
properties (that’s what CreatePerOwinContext
does) and then retrieved in the controller (e.g. HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()
).
Anyway, there’s no reason to settle for a “poor man’s DI”, so lets use StructureMap instead.
Starting from scratch
If you start with the Empty project template File->New->Project->Web->Asp.Net Web Application and then:
Because ASP.NET Identity has dependencies on Owin, and because you probably want to use the owin cookie middleware to handle signing in users, start by installing the Microsoft.Owin.Host.SystemWeb
NuGet package. You also need to install the ASP.NET Identity NuGet packages. Here’s the list that you can just copy&paste to the package manager console.
Here we’ll be using the EntityFramework version of the user store for ASP.NET Identity (user store italicized because the interface that exposes the functionality to actually save and retrieve users in ASP.NET Identity is named IUserStore
).
install-package Microsoft.Owin.Host.SystemWeb
install-package Microsoft.AspNet.Identity.Core
install-package Microsoft.AspNet.Identity.Owin
install-package Microsoft.AspNet.Identity.EntityFramework
And of course, install the StructureMap package for MVC:
install-package StructureMap.MVC5
Create your Owin Startup
class. Easiest way is to just right click on your project->Add New Item->Owin Startup Class.
You should add your own connection string in web.config for the database that ASP.NET Identity will be using. For example, if you want to use LocalDb and have the database called IdentitySetupWithStructureMap your connection string could look like this:
<connectionStrings>
<add name="IdentitySetupWithStructureMap" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\ProjectsV12;Integrated Security=SSPI;MultipleActiveResultSets=True;Initial Catalog=IdentitySetupWithStructureMap;AttachDbFileName=|DataDirectory|\IdentitySetupWithStructureMap.mdf" />
</connectionStrings>
This might not be the right connection string for you, for example your LocalDb might have a different name (you can check yours in Visual Studio’s SQL Server Object Explorer). If you are unsure check this great resource to help you setup your connection string.
StructureMap configuration
Before we dive in the StructureMap configuration for ASP.NET identity it helps to know how you would do it manually, i.e., actually new up everything you need.
The main class in ASP.NET Identity, and probably the only one you need to use is UserManager<T>
, where T will be a subclass of IdentityUser
(if you derive from IdentityUser
you can add your own properties to the user that gets saved, if you did not know about this you should check The good, the bad and the ugly of ASP.NET Identity.
UserManager<T>
has a dependency on IUserStore<T>
. The implementation we are going to use of IUserStore<T>
, UserStore<T>
, has a dependency on DbContext
(this is the EntityFramework implementation we’ve added through NuGet: Microsoft.AspNet.Identity.EntityFramework
).
So “manually” you could do this:
var dbContext = new IdentityDbContext("IdentitySetupWithStructureMap");
var userStore = new UserStore<IdentityUser>(dbContext);
var userManager = new UserManager<IdentityUser>(userStore);
And then you could setup your userManager, for example configure the password validator to only allow usernames with more than 6 characters:
userManager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6
};
Now that you know how to do it completely manually, if you can pause for a brief moment, go compare this with what gets generated with the default project template when you choose individual user accounts, let me know what you think in the comments.
There’s only four simple things that you need to know to understand the StructureMap configuration for this, they are:
- Given a constructor that expects a certain class as a parameter, specify which subclass to use
- How do you set properties using StructureMap (for the
UserValidator
,PasswordValidator
, etc inUserManager
) - How do select a constructor that is not the default constructor that StructureMap would normally use (one that is not the most specific, i.e., not one with the most dependencies).
- How to set the value of
value types
in the constructor, for example, the value of a string parameter (e.g.connectionString
).
Lets start with the setup for the UserManager<IdentityUser>
‘s dependency, IUserStory<IdentityUser>
(this code belongs inside the StructureMap Registry you are using to setup MVC, usually it’s called DefaultRegistry
):
For<IUserStore<IdentityUser>>()
.Use<UserStore<IdentityUser>>()
.Ctor<DbContext>()
.Is<IdentityDbContext>(cfg =>
cfg.SelectConstructor(() =>
new IdentityDbContext("value here does not matter, it's only for selecting the right ctor"))
.Ctor<string>()
.Is("IdentitySetupWithStructureMap"));
The For
Use
part is just how you map an interface to an implementation in StructureMap. Then .Ctor<DbContext>().Is<IdentityDbContext>(...)
is basically saying, for the DbContext
dependency use its subclass IdentityDbContext
. However IdentityDbContext
has many constructors, and the one we want to use is not the one with most dependencies (which would be the one StructureMap would use).
We want to use the IdentityDbContext
constructor that expects a single string parameter, the connection string. We use .SelectConstructor(() => new IdentityDbContext("value does not matter, this is just to let the compiler select the ctor")
to do that, and then we use .Ctor<string>
to specify the value we want for the string parameter, in this case the value of the connection string: .Is("IdentitySetupWithStructureMap")
(if the constructor had several string parameters you could pass the name of the parameter to .Ctor
, e.g. .Ctor<string>("nameOrConnectionString")
to disambiguate).
That takes care of UserManager<IdentityUser>
‘s dependencies. We still need, however, to set the PasswordValidator
and UserValidator
.
PasswordValidator
is the class that defines the minimum password requirements, for example that the minimum password length is 6 characters. UserValidator
is the class that checks if the username is valid, for example if you require that the username is an unique email address. There are more properties that you can setup on UserManager
, however the way they are setup is very similar to these two.
Because UserManager
does not implement an interface we have to use the class directly in our controllers. The way we configure a concrete class in StructureMap is by using the ForConcreteType<T>
method, in our case:
ForConcreteType<UserManager<IdentityUser>>()
.Configure
.SetProperty(userManager => userManager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6
})
.SetProperty(userManager => userManager.UserValidator =
new UserValidator<IdentityUser>(userManager));
Here’s the full listing for the Registry:
public DefaultRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
For<IUserStore<IdentityUser>>()
.Use<UserStore<IdentityUser>>()
.Ctor<DbContext>()
.Is<IdentityDbContext>(cfg => cfg.SelectConstructor(() => new IdentityDbContext("connection string")).Ctor<string>().Is("IdentitySetupWithStructureMap"));
ForConcreteType<UserManager<IdentityUser>>()
.Configure
.SetProperty(userManager => userManager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6
})
.SetProperty(userManager => userManager.UserValidator = new UserValidator<IdentityUser>(userManager));
}
And there you go, with this configuration you can now add UserManager
to your controllers as a dependency, for example:
public class HomeController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
public HomeController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
...
I’ve added an example project in Github that uses this setup and a few extra bits. It allows you to create, list and delete users, check it out by cloning the repository
git clone https://github.com/ruidfigueiredo/MvcAndAspNetIdentitySetupWithStructureMapExample
Drop me a line in the comments if you are interested in a summary (cheat sheet) of how to do the most common operations with ASP.NET Identity, for example, create users, delete users, reset a user’s password without requiring email messages, setting up email messages for email confirmation and password reset, etc.