1

I am trying to build a simple login system from the ground up, using the code-first approach with ASP.NET MVC v5, Entity Framework v7, and Identity v3. I'm modeling my app after the ASP.NET MVC app with individual user logins template that Visual Studio comes with.

All I want is for the user to create an account, and for that account to be saved in a database.

Here is the code I have so far:

Startup.cs:

public class Startup
{
    public IConfigurationRoot Configuration { get; set; }
    public Startup()
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");
        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());
        app.UseStaticFiles();
        app.UseIdentity();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

    public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}

appsettings.json contains this code for the connection to the database:

"Data": {
  "DefaultConnection": {
    "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=SimpleAuthenticationApp;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Here's the code for the Register POST action in Controllers/AccountController.cs:

    [HttpPost]
    public async Task<IActionResult> Register (RegisterViewModel model)
    {
        try
        {
            var user = new ApplicationUser { UserName = model.Email };
            IdentityResult result = await _userManager.CreateAsync(user, model.Password);
            Console.WriteLine(result);
            return View("Home", "Index");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return View();
        }
    }

In this code, RegisterViewModel is just a ViewModel with fields for Email, Password, and ConfirmPassword. The Account/Register view is just a form that asks for these fields. ApplicationUser is a class that extends from IdentityUser.

In the POST route, I set a break point at the try block, and when it enters the catch block, the exception reads "Invalid object name AspNetUsers."

Before I create the first user in this app, there's no database. I register a new user, the app takes me to an error page reading, "Applying existing migrations for ApplicationDbContext may resolve this issue" with a button to apply migrations. When I hit the button, the database is created. I've noticed that when I run the default MVC with Users app, there's a Migrations folder containing 00000000000000_CreateIdentitySchema.cs and ApplicationDbContextModelSnapshot.cs that look like they contain the settings to create the database with tables needed. I tried using those files in my app, but it didn't make any difference.

My questions:

  • How does Identity/Entity Framework create the database with tables for user information? It seems strange that I need to "Apply migrations" before the database for the app can be created.

  • What can I do in my own app to get a simple user login working? Other approaches or frameworks are welcome.

jmk22
  • 1,104
  • 4
  • 15
  • 27

2 Answers2

2

EntityFramework uses a Continuous Migration concept to upgrade your database schema when required. By default, the initial migrations create the user/identity tables as you've already discovered. You don't have to do anything with the code in the Migrations folder directly; if you set up a Migration initialiser then the database can be initialised/upgraded on startup:

I recommend reading through this walk through to get a better understanding of what's going on and what you can do with it:

https://msdn.microsoft.com/en-us/data/jj591621.aspx

The auto-initialisation/upgrade scenario I mentioned above is covered in this article.

Robert Foster
  • 2,317
  • 18
  • 28
0

Honestly, I had to write a long article about this here: https://medium.com/@goodealsnow/asp-net-core-identity-3-0-6018fc151b4 In general, you can utiilzie the dotnet cli to deploy migrations dotnet ef migrations add Version2CoolWaves -o Data\Migrations

But read my full article for step by step tutorial.

hidden
  • 3,216
  • 8
  • 47
  • 69