Search code examples
c#asp.netasp.net-mvcentity-frameworkef-model-first

ASP.NET MVC 5 Identity with Model First


I'm developing a web application and I would like to implement Identity. I've done a couple of tests and it's pretty easy to implement when using a Code First approach.

My issue is that I can't get it to work with a Model First approach. I would like to define my models in the .edmx file, and generate my database using the "Generate database from model" option.

Here's what I've done:

I started from the default ASP .NET Web Application template, including the "Individual User Account" authentication. Then I registered a user in order for entity framework to generate the needed tables in the default database. Then I added the "ADO .NET Entity Data Model" to my project, and chose the "EF Designer from Database" option. It has been generated successfully with the existing tables created by Identity. I changed the connection string in the IdentityModels:

public ApplicationDbContext()
        : base("MyConnectionStringName", throwIfV1Schema: false)
{
}

But after this, when I try to register a user, I get the following error:

"Unable to load the specified metadata resource."

Previously, I also had an error: "The entity type ApplicationUser is not part of the model for the current context."

Is it actually possible to use Identity with a Model First approach ? If yes, what am I doing wrong ?


Solution

  • I said I'll post something in order to explain how I managed to get this working. I struggled to find some documentation and tutorials about using Identity with a Model First approach, so here it comes.

    Firstly, I found this genius article from Ben Foster: http://benfoster.io/blog/aspnet-identity-stripped-bare-mvc-part-1

    This article discuss about how to implement an "Identity Stripped Bare". Reading it and following the steps allowed me understand how to use identity from scratch (you can see at the beggining that he generates an MVC 5 project with no authentication system). If you want the code of this "Naked Identity", here it is: https://github.com/benfoster/NakedIdentity

    The first step was to generate the database. In the Naked Identity code, the v1.0 of Identity is used. Some things are different (a couple table properties for example), but it stays mostly identical. To create a database usable by Identity, I simply ran the template MVC 5 project, registered a user for the table to be created with the Code First approach, and then copied those tables needed by Identity in my empty database.

    Once this was done, I generated my .edmx using the freshly created database. A connection string is added to the web.config. A connection string may already exist as "DefaultConnection". You need to keep this one as well.

    Basically, those 2 connection strings are needed because, Identity is gonna use the default one, and the .edmx is gonna use the other one. It is not possible to use the same one for both as the .edmx connection string needs metadata, that are not supported by identity. Thus, those 2 connection strings are different, but I modified them so they can refer to the same database.

    <connectionStrings> <add name="DefaultConnectionString" connectionString="Data Source=(LocalDb)\v11.0; Initial Catalog=DatabaseName; Integrated Security=True" providerName="System.Data.SqlClient" /> <add name="EntitiesConnectionString" connectionString="metadata=res://*/Models.WebAppModel.csdl|res://*/Models.WebAppModel.ssdl|res://*/Models.WebAppModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDb)\v11.0;initial catalog=DatabaseName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" /> </connectionStrings>

    The first connection string is the one you're gonna use with entity. So here is how the IdentityDbContext is initialized:

    `` public class AppDbContext : IdentityDbContext { public AppDbContext() : base("QualityWebAppDbEntitiesDefault", throwIfV1Schema: false) { }

        public static AppDbContext Create()
        {
            return new AppDbContext();
        }
    }
    

    `` (you can find the AppUser definition in the NakedIdentity sources)

    And for my .edmx, the initialization looks like this:

    public partial class QualityWebAppDbEntities : DbContext { public QualityWebAppDbEntities() : base("name=QualityWebAppDbEntities") { } }

    Hope this will help people that want to use a Model First approach with Identity.