MVC, MVVM and Frameworks

I’ve been writing a whole bunch about MVC architectures – client side and server side.  But I hit a problem.  You see, MVC and MVVM are pretty simple concepts.  Here is a typical diagram that I see when looking at MVC descriptions:

blog-08012015-1

It’s nice and simple.  The controller loads the model and passes some form of data to the View.  The problem is this – where is the user and where is the data?  How do these actually interact?  This is actually a key point in understanding the architecture and the place that frameworks – any framework – occupies in the architecture.  I think the following is a much more representative architectural diagram:

blog-08012015-2

This makes more sense to me.  The user submits a request to a dispatcher.  The dispatcher decides which controller to pass the request to.  The controller asks the adapter to give it one or more models to complete the request.  In the case of MVVM, these models are transitioned into a View-Model, usually through some sort of data binding.  This new model (or view-model) is passed into the View rendering system, which renders the appropriate view and kicks it back to the core dispatcher so that the dispatcher can respond to the user.

It’s much more messy than the plain MVC (or MVVM) design pattern.  However, it’s implementable and I can see the pieces I need to implement in order to achieve the desired web application.  This architecture can be implemented on the client side or the server side and both sides have frameworks that assist.

Frameworks provide some sort of functionality that allow you to ignore the boiler-plate code that inevitably comes with writing such an architecture.  Most frameworks have some sort of dispatcher (normally called a router, but they do much more than that) and most frameworks have some sort of adapter logic (mostly called an ORM or Object Relational Mapper).  In between, frameworks enforce a pattern for controllers, models and views that can be used to enforce consistency across the application.

On the server side, I have two go-to languages – C# and JavaScript.  I use ASP.NET as my framework of choice on the C# server side.  I can map my visual directly to ASP.NET:

  • ASP.NET provides the dispatcher, with an ability to configure a route map in it’s startup class.
  • The Controller class can be inherited to create custom controllers
  • The Model is a plain-old class
  • The View is handled by Razor syntax
  • The Adapter is generally handled by Entity Framework.

For server-side JavaScript, the mapping is a little more messy:

I haven’t really gotten into Models and Adapters, although I can see libraries such as Mongoose (for MongoDB) playing a part there.  However, there are Node/Express MVC frameworks out there – I want to investigate Locomotive and SailsJS at some point, for example.

On the client side, things are definitely more messy.  There are a host of different frameworks – Angular, Aurelia, Ember, Knockout, Meteor, React / Flux, along with a host of others.  I’ve found the TodoMVC site to have a good list of frameworks worth looking at.  Some of these are being upgraded to handle ES2015 syntax, some are already there and some are never going to be there.

One thing to note about frameworks.  They are all opinionated.  ASP.NET likes the controllers to be in a Controllers namespace.  Angular likes you to use directives.  Aurelia likes SystemJS and jspm.  Whatever it is, you need to know those opinions and how they will affect things.

The web isn’t the only place one can use frameworks.  The MVC architecture is not limited to web development – it’s constant across applications of any complexity.  For example, you can see MVC in WinForms, Mobile applications, Mac OSX Applications and Linux Applications.

I want my application to be rendered client-side, which means I need to take a look at client-side frameworks.  My working list is:

I’m not going to bother with Backbone, Meteor, Knockout or any other older or smaller framework.  This is my own time and I don’t want to spend a ton of time on investigation.  I pretty much know what Aurelia can provide.  To investigate the others I needed a small site I could implement – something that wasn’t “just another task organizer” (TodoMVC).  To that end, I decided to create a three page application.

  • Page 1 – the home page – will get loaded initially and contain a Polymer-based carousel
  • Page 2 – a linked page – will load data from the Internet (the Flickr example from the Aurelia app)
  • Page 3 – an authenticated page – will load data from the local server if the user is authenticated

In addition to the three pages, I’m going to ensure that the navigation is separated logically from the actual pages and that – where possible – the pages are written in ES2015.  I want separation of concerns, so I expect the models to be completely separate from the views and controllers.

Each one will be implemented on top of a Node/ExpressJS server that serves up just the stuff needed.  In this way, I will be able to see the install specifics.  You can see my starter project on my GitHub Repository.  I hope you will enjoy this series of blog posts as I cover each framework.

ASP.NET MVC6 Identity Part 1 – The Database

About a month ago, I published a series of nine articles that tackled ASP.NET Identity in the ASP.NET MVC5 framework using Beta-3 of the framework. Well, Beta-4 is now out, along with Visual Studio 2015 RC and things have changed. As a result, the next five articles will go through the same process as before.

As a reminder, this is what we want to achieve:

  1. Setting up the Identity Database
  2. Logging in as a normal user
  3. Registering a new account
  4. Handling forgotten password requests
  5. Handling Social Logins

I didn’t do that last one the last time because the support from the framework wasn’t included yet. This time I’m definitely going to take a look at that. To start with, I have a base MVC5 project and you can download it at my GitHub Repository (Sorry – the newer versions of ASP.NET5 don’t allow this to compile, so I’ve deleted the repository to reduce confusion). This project currently has no identity provisions, except for a Sign In link that I haven’t filled in yet. You can run it and a Lorem Ipsum type home page will be displayed.

Setting up the Database

As before, I am going to need some packages. The new packages for supporting Identity are as follows:

  1. EntityFramework.Core
  2. EntityFramework.SqlServer
  3. Microsoft.AspNet.Identity
  4. Microsoft.AspNet.Identity.EntityFramework

As before, I’m going to be using Entity Framework v7 to handle the database functionality, and ASP.NET Identity for the authentication and authorization piece. There isn’t a whole lot of documentation about EF7 right now. Also, there are other packages that could be doing Identity – including Microsoft.AspNet.Security packages. This means that the end method hasn’t probably been settled yet and there may be more changes in the future.

Back to this release. I updated the Startup.cs file to include this:

        public Startup()
        {
            Configuration = new Configuration()
                .AddJsonFile("./config.json")
                .AddJsonFile("./config-local.json")
                .AddEnvironmentVariables();
        }

I’m going to check in the config.json file, but not the config-local.json file. If I include any credentials, I’ll put them in the config-local.json file. This allows me to check in something to show the structure but then override it with another configuration file. If you are following along, make sure you create a config-local.json file with a blank object in it.

I’ve added my database connection string to the config.json:

{
  "Mode": "Development",
  "Database": {
    "Connection": "Server=(localdb)\mssqllocaldb;Database=TestDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "DefaultUser": {
    "Username": "admin",
    "Password": "Chang3Me!"
  }
}

Last time, I deliberately modified the password to be non-secure. Not so this time – I’ve got my strong password right from the start. Again – you can override the default user password in your own config-local.json file.

The next task is to configure an application database context, linking it to Entity Framework and ASP.NET Identity as well. This is done in the ConfigureServices method inside Startup.cs:

        public void ConfigureServices(IServiceCollection services)
        {
            // Configure our application database context to be Entity Framework backed by SQL Server
            services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext(options =>
                    options.UseSqlServer(Configuration.Get("Database:Connection")));

            // Specify the configuration of our Application database context
            services.Configure(options =>
            {
                options.DefaultUsername = Configuration.Get("DefaultUser:Username");
                options.DefaultPassword = Configuration.Get("DefaultUSer:Password");
            });

            // Configure ASP.NET Identity to use our Identity-based application context
            services.AddIdentity()
                .AddEntityFrameworkStores()
                .AddDefaultTokenProviders();

            services.AddMvc();
        }

Finally, we need to set up the application to use identity and call into our context to initialize the database. This is done in the Configure method in Startup.cs:

        public void Configure(IApplicationBuilder app)
        {
            app.UseErrorPage(ErrorPageOptions.ShowAll);
            app.UseStaticFiles();
            app.UseIdentity();

            app.UseMvc(r ==>
            {
                r.MapRoute(name: "default", template: "{area=Public}/{controller=Home}/{action=Index}/{id?}");
            });

            ApplicationDbContext.InitializeDatabaseAsync(app.ApplicationServices).Wait();
        }

So far (aside from needing EntityFramework.Core as a package), this is all the same as the beta-3 framework. I need to write the ApplicationDbContext class and its associated options class, plus my ApplicationUse model for the identity database. All my database code is going to go in the Grumpy.Wizards.Database namespace – this includes all three of these files. First up is Database/ApplicationUser.cs:

using Microsoft.AspNet.Identity.EntityFramework;

namespace Grumpy.Wizards.Database
{
    public class ApplicationUser : IdentityUser
    {
    }
}

Next is the Database/ApplicationDbContextOptions.cs file:

namespace Grumpy.Wizards.Database
{
    public class ApplicationDbContextOptions
    {
        public string DefaultUsername { get; set; }

        public string DefaultPassword { get; set; }
    }
}

These are identical to the classes that I used in Beta-3. The last time around, I split the database context into a static initialization class and a non-static context class. I’ve combined them this time into a single file Database/ApplicationDbContext.cs:

using System;
using System.Threading.Tasks;

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Data.Entity.SqlServer;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;

namespace Grumpy.Wizards.Database
{
    public class ApplicationDbContext : IdentityDbContext
    {
        const string adminRole = "admin";

        public static async Task InitializeDatabaseAsync(IServiceProvider serviceProvider)
        {
            using (var db = serviceProvider.GetRequiredService())
            {
                var sqlDb = db.Database as SqlServerDatabase;
                if (sqlDb != null)
                {
                    await sqlDb.EnsureCreatedAsync();
                    await CreateAdminUser(serviceProvider);
                }
            }
        }

        private static async Task CreateAdminUser(IServiceProvider serviceProvider)
        {
            var options = serviceProvider.GetRequiredService<IOptions>().Options;
            var userMgr = serviceProvider.GetRequiredService<UserManager>();
            var roleMgr = serviceProvider.GetRequiredService<RoleManager>();

            if (!await roleMgr.RoleExistsAsync(adminRole))
            {
                await roleMgr.CreateAsync(new IdentityRole(adminRole));
            }

            var user = await userMgr.FindByNameAsync(options.DefaultUsername);
            if (user == null)
            {
                user = new ApplicationUser { UserName = options.DefaultUsername };
                var userCreationResult = await userMgr.CreateAsync(user, options.DefaultPassword);
                if (userCreationResult.Succeeded)
                {
                    await userMgr.AddToRoleAsync(user, adminRole);
                }
            }
        }
    }
}

The actual code for setting up the database is identical to the code used in beta-3. At this point, you are probably wondering why I didn’t just refer people to the other article. Well, I like tutorials to stand alone, especially when there is a sequence of articles. I also wanted to show off that you can integrate the creation of the database with the identity database context – there is no need for multiple classes here. Since these two elements deal with the same thing (the database), it’s appropriate that they are together.

Testing Your Work

Run the project and wait for the site to load (which it should do). Then use the View menu to bring up the SQL Server Object Explorer. Add the (localdb)mssqllocaldb database instance. Open up the Databases, then TestDb and take a look at the dbo.AspNetUsers table.

blog-code-0529-1

If you right click and View the data, you should see the admin user has been created. That’s all we can hope for right now as we have not wired up the login form as yet. More on that in the next article.

ASP.NET vNext Identity Part 2 – The Login Process

In the first article in this series I went through the process of setting up a database for identity storage and storing a single admin user in the database. However I still have not enabled logins to my application yet. I need to enable identity within the application, set up a view that needs to be authenticated and write some views to handle logging in. I am not going to be adding registration in this article – that’s the subject for another day. You can retrieve the starting point for this article in the AspNetIdentity project on my GitHub repository.

The first stop is to my Startup.cs file. I need to actually enable Identity in the same way as I enable static files, detailed error pages, browser link, MVC and just about anything else. I need to tell the pipeline that I am using identity. Like this:

        
        public void Configure(IApplicationBuilder app)
        {
            // A 404 Error Page with useful information
            app.UseErrorPage(ErrorPageOptions.ShowAll);

            // Serve up the stuff in wwwroot
            app.UseStaticFiles();

            // Authentication and Authorization
            app.UseIdentity();

            // Configure ASP.NET MVC6
            app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}"
                    );
                });

            // Create a default user
            IdentityDbOperations.InitializeIdentityDbAsync(app.ApplicationServices).Wait();
        }

Just one line was added to this method. Now I need to get some authentication going. I want my whole application to require authentication except where it isn’t possible – like the login screen. I have a HomeController right now so let’s add authentication to that. Here is the whole file:

using Microsoft.AspNet.Mvc;

namespace AspNetIdentity.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }
}

That [Authorize] tag tells the ASP.NET application that we want authentication. Let’s run our application and see what happens:

blog-code-0403-1

This is just part of the detailed error report I get when I get the 404 result. The system is redirecting me to a login page because I’m not authorized to be on the home page. However the login page doesn’t exist. To create one I’m going to need an Account controller and a Login view. Let’s start with the controller. Add a new MVC Controller Class called AccountController. I’ve broken the class down into manageable chunks below:

namespace AspNetIdentity.Controllers
{
    public class AccountController : Controller
    {
        public AccountController(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager)
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }

        public UserManager<ApplicationUser> UserManager
        {
            get;
            private set;
        }

        public SignInManager<ApplicationUser> SignInManager
        {
            get;
            private set;
        }

When my AccountController first gets created, it is passed the user manager and sign-in manager objects that are part of the Identity Framework (using Dependency Injection). I need to store those for later on. Those objects are stored in two properties that I’ve set to be read-only to the outside world.

        /**
         * GET /Account/Login
         */
        [HttpGet]
        [AllowAnonymous]
        public IActionResult Login(string returnUrl = null)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

When first entering the login process, we saw that it does a GET of /Account/Login with a returnUrl field. This method processes that request and returns the login page. More on that later.

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            ViewBag.ReturnUrl = returnUrl;
            if (ModelState.IsValid)
            {
                var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
                if (result.Succeeded)
                {
                    return RedirectToLocal(returnUrl);
                }
                if (result.IsLockedOut)
                {
                    return View("Lockout");
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                    return View(model);
                }
            }

            // If we got this far, something failed - redisplay the form
            return View(model);
        }

This is a little more complex, but should be fairly readable. We first of all check that our parameters (which are contained in the LoginViewModel – more on that later) are good. If they are, then call the password checker in the sign-in manager. There are three possible outcomes – the login succeeded, the user is locked out or “something else”. I’m going to assume “something else” is a bad username or password.

If the login is successful then the user is authenticated and gets redirected back to where they were. If not, then display the login page with appropriate information about the failure.

To wrap this up I need to write the RedirectToLocal helper method:

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            } else
            {
                return RedirectToAction("Index", "Home");
            }
        }

This basically says “if you specified a valid local URL, then go there. Otherwise go to the home page.”

There are two additional pieces I need to complete the sequence. The first is a basic ViewModel for the Login action. I’ve created a new directory called ViewModels and placed the LoginViewModel.cs in there:

using System.ComponentModel.DataAnnotations;

namespace AspNetIdentity.ViewModels
{
    public class LoginViewModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }

    }
}

ViewModels are just like models, except they model the data coming in from the client rather than the data going out to the client. You can add decorators to the view model properties to give the view some information on how to render it. In this case, I’m telling the view that the username and password are required fields in the form and have specific default display attributes.

The second piece I need to complete the login sequence is a login view. I’m going to create a new layout file for the login view. I’ve placed this in Views/Layout/LoginPage.cshtml with the following contents:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="~/Style/Login.css">
    <title>@ViewBag.Title</title>
</head>
<body>
      @RenderBody()
</body>
</html>

I’ve also got a Views/Account/Login.cshtml view file which I will build. My initial contents (it will grow) are as follows:

@model AspNetIdentity.ViewModels.LoginViewModel

@{ 
    Layout = "~/Views/Layout/LoginPage.cshtml";
    ViewBag.Title = "Log In";
}

<div class="login-form-outer"></div>

I’m stopping there temporarily because I want to show this off in order. Right now, my LESS file is as follows:

@import (less) "mixins/reset.less";

@loginbox-height: 200px;
@loginbox-width: 200px;

body {
    background-color: #666666;
}

.login-form-outer {
    border: 1px solid #333333;
    border-radius: 16px;
    background: white;

    width: @loginbox-width;
    height: @loginbox-height;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -(@loginbox-width / 2);
    margin-top: -(@loginbox-height / 2)
}

This uses a technique that I found on css-tricks.com for centering the box on the page. After this, everything else is in the form, so I won’t be worrying about the CSS too much. If you want to see the whole CSS, check out the project on GitHub at the end.

Now, back to our Login view. The next thing we have to do is to bring in the form. This is the bulk of the view:

@model AspNetIdentity.ViewModels.LoginViewModel

@{
    Layout = "~/Views/Layout/LoginPage.cshtml";
    ViewBag.Title = "Log In";
}

<div class="login-form-outer">
    @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
    {
        @Html.AntiForgeryToken()
        <h4>Use a Local Account to log in.</h4>
        <hr>
        @Html.ValidationSummary(true)
        <div class="form-group">
            @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.UserName)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Password)
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <div class="checkbox">
                    @Html.CheckBoxFor(m => m.RememberMe)
                    @Html.LabelFor(m => m.RememberMe)
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Log in" class="btn btn-default" />
            </div>
        </div>
    }
</div>

Run this and see what you get. You should be able to enter any username and password – wrong ones will get you an Invalid username or password message. The correct admin password will get you to your home screen. We have not integrated our identity information into the existing views yet – we’ve just authenticated. My simple home page looks like this now:

@{
    ViewBag.Title = "Home Page";
}

<h1>Hooray!  Let's take a look at the user</h1>

<p>Everything is in User.Identity</p>
<ul>
    <li>AuthenticationType: @User.Identity.AuthenticationType</li>
    <li>IsAuthenticated: @User.Identity.IsAuthenticated</li>
    <li>Name: @User.Identity.Name</li>
    <li>IsInRole("admin"): @User.IsInRole("admin")</li>
</ul>

As you can see when you run this I can get the username, the admin status and the authentication type.

In my next post I will take a look at what is required to register a new account for my application. Until then, check out my GitHub Repository for the latest code bundle.

ASP.NET vNext Identity Part 1 – The Database

I’m progressing in my investigation of web applications using the latest tools and now it’s time to tackle identity. I have a few requirements here:

  1. I want an administrative user that doesn’t rely on anything else
  2. I also want to register users via Facebook, Twitter, Google or Microsoft

I’m going to have to get down and dirty with Entity Framework (an ORM for SQL databases) and the ASP.NET Identity 3.0 framework. This post is all about the pre-requisites – getting a database set up that is usable by the identity framework.

I’ve already got a basic MVC6 setup with a controller (HomeController) and View (Index.cshtml) so I’m not going to include those details here. I’m just concentrating on the extra pieces you need for setting up Identity.

I’m going to use a SQL Express database during development since that is located on the local machine and I can blow it away if I need to. I’m planning on using an Azure-based SQL database in production since that allows me to scale my web site using auto-scale in Azure. Both of those use the standard Microsoft SQL Server plugins to connect. I need some packages from NuGet (registered in my project.json file) to effect that. Here is the list of new (additive) packages:

  1. EntityFramework.SqlServer
  2. Microsoft.AspNet.Identity
  3. Microsoft.AspNet.Identity.EntityFramework
  4. Microsoft.Framework.ConfigurationModel.Json

The latter is not strictly needed. It’s used for specifying configuration options in a JSON file and I’m going to want to set certain configuration options up, so a JSON file is a good place for them. There are other ways of handling this.

Talking of the configuration file, I’m going to call my configuration file config.json. I know – it’s an original name. Place the config.json file in the root of your project. Here are the contents:

{
    "AdminUser": {
        "Username": "admin",
        "Password": "changeme"
    },
    "Database": {
        "ConnectionString": "Server=(localdb)\mssqllocaldb;Database=TestDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
}

Spoiler: There is a mistake in this file. I’ve deliberately made the mistake so that I can demonstrate something later on and the fix is easy.

The AdminUser block is for specifying the username and password for the administrative user when it is first created. Once it is created, these entries are ignored. The connection string points to a test database on my local SQL Express instance. I will change this when I move to production to point to the Azure database instance. If you already have a database because of your application then you can use that.

Let’s take a look at my Startup class in Startup.cs in pieces (you can string them all together to get the complete picture):

    public class Startup
    {
        public Startup()
        {
            Configuration = new Configuration()
                .AddJsonFile("config.json")
                .AddEnvironmentVariables();
        }

        public IConfiguration Configuration
        {
            get;
            private set;
        }

I first of all load my config.json file into a Configuration object. Then I allow the operator to override any of my settings with environment variables. Louis Dejardin did a really good post on configuration so I won’t go into it here.

        public void ConfigureServices(IServiceCollection services)
        {
            // Entity Framework Service backed by SQL Server
            services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext(options =&gt;
                    options.UseSqlServer(Configuration.Get("Database:ConnectionString")));

            // Configure the identity service based on our configuration
            services.Configure(options =&gt;
            {
                options.DefaultAdminUserName = Configuration.Get("AdminUser:Username");
                options.DefaultAdminPassword = Configuration.Get("AdminUser:Password");
            });

            // Now add the entity framework backed identity service
            services.AddIdentity()
                .AddEntityFrameworkStores()
                .AddDefaultTokenProviders();

            // ASP.NET MVC6 Service
            services.AddMvc();
        }

Next I am getting into services. Prior to this change I only had the MVC6 service, which is still at the bottom of the method. Let’s take a look at the rest of it. Firstly I add Entity Framework as a service, making it talk to SQL Server and then setting up the connection string from our configuration.

I am then adding a configuration object based on a model (more on that later) – specifically setting up the Admin username and password in that model.

Finally, I’m setting up Identity to use my ApplicationUser model and my ApplicationDbContext object that I’ve used to configure EntityFramework. This is basically the glue between the identity system and Entity Framework (and hence my database).

        public void Configure(IApplicationBuilder app)
        {
            // A 404 Error Page with useful information
            app.UseErrorPage(ErrorPageOptions.ShowAll);

            // Serve up the stuff in wwwroot
            app.UseStaticFiles();

            // Configure ASP.NET MVC6
            app.UseMvc(routes =&gt;
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}"
                    );
                });

            // Set up the Identity database
            IdentityDbOperations.InitializeIdentityDbAsync(app.ApplicationServices).Wait();
        }
    }

The other part of my startup is the Configure method. Here I am just calling an async routine to initialize my database if it isn’t already set up.

There are three models that I need to write:

  1. ApplicationDbContext
  2. ApplicationUser
  3. IdentityDbContextOptions

The ApplicationUser represents the user that is being logged in. It’s modeled after the IdentityUser, so it is fairly straight forward. Similarly, the ApplicationDbContext is modeled after an IdentityDbContext but based on my new ApplicationUser. I put these definitions in the same file (ModelsApplicationDbContext.cs)

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace AspNetIdentity.Models
{
    public class ApplicationDbContext : IdentityDbContext
    {
    }

    public class ApplicationUser : IdentityUser
    {
    }
}

Defining the ApplicationUser and ApplicationDbContext like this allows me to add things to the model for the user if I so desire. I can’t change the IdentityUser. Having said that, the IdentityUser has a bunch of general properties on a user that are useful already so I’m not sure I’ll be doing much extending. You can view these objects as follows: ApplicationUser is the model for my user. ApplicationDbContext is a database object that knows how to update the database when users get added and removed from my application.

The IdentityDbContextOptions model is used for passing the default Administrator username and password around the application. It’s pretty basic – just two properties:

namespace AspNetIdentity.Models
{
    public class IdentityDbContextOptions
    {
        public string DefaultAdminUserName
        {
            get;
            set;
        }

        public string DefaultAdminPassword
        {
            get;
            set;
        }
    }
}

The final step of the process is to look at the IdentityDbOperations class. This is the class that sets up the initial data. I want to do three things in this class:

  1. Create the database (if it doesn’t exist).
  2. Create an “admin” role (if it doesn’t exist).
  3. Add the admin user to the “admin” role (it it isn’t already there).

In short, if things break – I want to get the database back to a minimally viable state so I can log in again. Here is the code in sections so I can comment.

namespace AspNetIdentity.Models
{
    public class IdentityDbOperations
    {
        // The default administrator role
        const string adminRole = "admin";

        public static async Task InitializeIdentityDbAsync(IServiceProvider serviceProvider)
        {
            using (var db = serviceProvider.GetRequiredService())
            {
                var sqlDb = db.Database as SqlServerDatabase;
                if (sqlDb != null)
                {
                    // Create the database if it does not already exist
                    Debug.WriteLine("InitializeIdentityDbAsync: Ensuring Database exists");
                    await sqlDb.EnsureCreatedAsync();
                    // Create the first user if it does not already exist
                    await CreateAdminUser(serviceProvider);
                }
            }
        }

This is the entry point into the class and is called from my Startup.Configure() method. It ensures the database is created and creates it if the database does not exist (point 1 above). Then it will try to create the admin user (below):

        private static async Task CreateAdminUser(IServiceProvider serviceProvider)
        {
            var options = serviceProvider.GetRequiredService&lt;IOptions&gt;().Options;
            var userManager = serviceProvider.GetRequiredService&lt;UserManager&gt;();
            var roleManager = serviceProvider.GetRequiredService&lt;RoleManager&gt;();

            // If the admin role does not exist, create it.
            Debug.WriteLine("CreateAdminUser: Ensuring Role admin exists");
            if (!await roleManager.RoleExistsAsync(adminRole))
            {
                Debug.WriteLine("CreateAdminUser: Role admin does not exist - creating");
                var roleCreationResult = await roleManager.CreateAsync(new IdentityRole(adminRole));
                DumpIdentityResult("CreateAdminUser: Role Creation", roleCreationResult);
            }
            else
            {
                Debug.WriteLine("CreateAdminUser: Role admin exists");
            }

            // if the user does not exist, create it.
            Debug.WriteLine(String.Format("CreateAdminUser: Ensuring User {0} exists", options.DefaultAdminUserName));
            var user = await userManager.FindByNameAsync(options.DefaultAdminUserName);
            if (user == null)
            {
                Debug.WriteLine("CreateAdminUser: User does not exist - creating");
                user = new ApplicationUser { UserName = options.DefaultAdminUserName };
                var userCreationResult = await userManager.CreateAsync(user, options.DefaultAdminPassword);
                DumpIdentityResult("CreateAdminUser: User Creation", userCreationResult);
                if (userCreationResult.Succeeded)
                {
                    Debug.WriteLine("CreateAdminUser: Adding new user to role admin");
                    var roleAdditionResult = await userManager.AddToRoleAsync(user, adminRole);
                    DumpIdentityResult("CreateAdminUser: Role Addition", roleAdditionResult);
                }
            }
            else
            {
                Debug.WriteLine("CreateAdminUser: User already exists");
            }
        }

This is a little more complex. In identity land there is a user manager – an object that manages, well, users. There is also a role manager – an object that manages roles. Roles are collections of users that share common permissions and are used for authorization within the application. A user does not need to have a role.

The first thing we do is check to see if the role “admin” exists. If it doesn’t, we try to create it. Then we move onto the user. Just like with the role, we check to see if our admin user exists. if the user does not exist, then we create it and add it to the role we just created.

This is one area of the application that doesn’t get exercised much so I’ve added some debugging statements to it. In particular, I want to see the results of all these additions and changes. Each of the changes returns an IdentityResult. In that object are two properties that are interesting:

  1. Succeeded is true if the operation succeeded
  2. Errors is a list of errors that happened if the operation was not successful

I call DumpIdentityResult (below) to dump these out to my Debug window. You can find this window in the Output window (normally at the bottom of the screen) – just select “Show output from: Debug”.

        private static void DumpIdentityResult(string prefix, IdentityResult result)
        {
            Debug.WriteLine(String.Format("{0}: Result = {1}", prefix, result.Succeeded ? "Success" : "Failed"));
            if (!result.Succeeded)
            {
                foreach (var error in result.Errors)
                {
                    Debug.WriteLine(String.Format("--&gt; {0}: {1}", error.Code, error.Description));
                }
            }
        }
    }
}

That’s pretty much it for code. I have not added Identity yet – that’s my next task. However, I want to ensure my database is set up properly. To do this, run the project and wait for your initial Home page to load. Now, let’s go look at the database. With the project still running, use View -> Server Explorer to open up the Server Explorer. It will look like this:

blog-code-0402-1

Right-click on Data Connections and select Add Connection… Enter (localdb)mssqllocaldb in the server name box and click on Refresh. It will look like this:

blog-code-0402-2

Note the drop down for the database name. Select the TestDb database and click on Ok. A new node will appear under the Data Connections – that is your database. Expand it, and then expand the Tables node. It will look something like this:

blog-code-0402-3

You can right-click on any table to see the contents. Just select Show Table Data. We are concerned with three tables. The first is the AspNetRoles table – we created an admin role and it should be there. Luckily for me, it is. The next table is the AspNetUsers table – that holds the user names. Opening that shows a single row with a whole lot of NULL entries – not what I wanted to see. I wanted to see my admin user. The final table is the AspNetUserRoles table – this would contain an association between my role and my user. However my user doesn’t exist and so this table is empty as well. What went wrong?

Fortunately, I added some debugging to my database creation methods. Scrolling back in my Debug window, I see the following:

blog-code-0402-4

I can clearly see from this that the user creation failed (which I knew anyway), but it gives me the reasons. There is a default password complexity requirement and my password does not meet it. I can go ahead and change my password or I can adjust the password complexity requirements. The simplest mechanism right now is to adjust the default password in config.json to match the requirements. I changed mine to Chang3Me!.

See, I told you there was an error!

Once the change is made, I restarted the server and did the same checks as before. Looking at the database now, you can see two rows in the AspNetUsers table – the NULL one and one for the admin user. You will note that the password is hashed and several other fields have been filled in for you.

Also, if you look in the AspNetUserRoles table, you will see a two column row with UserId set to the Id of the user in AspNetUsers and RoleId is set to the Id of the user in AspNetRoles.

Want one of those fancy database diagrams for this database? I did. Unfortunately, the tool that would generate those (SQL Server Data Tools) isn’t out for Visual Studio 2015 yet. So that will have to wait.

In the next post I will take a look at authentication and authorization and see about getting this user to log in to the application.

If you are interested in the code after this project is done, then take a look at my GitHub repository. It’s all in the AspNetIdentity project.