9

I want to change the names of the tables used by ASP.NET Identity 2.0. I've seen various similar questions but nothing that solves my problem. For instance this type of solution: http://www.goatly.net/customizing-table-names-for-identitydbcontextwithcustomuser-data-contexts seems to depend on Code First(?). At any rate implementing OnModelCreating does nothing for me. I've basically renamed the AspNetUsers and similar tables to my own names and want to be able to use these. I have an existing EF context (MyContext) that I want to use, so I modified it to derive from IdentityDbContext (editing the t4 template), and then in Startup.Auth I have:

        UserManagerFactory = () =>
        {
            var context = new MyContext();

            Database.SetInitializer<MyContext>(new IdentityDbInitializer());

            var userStore = new UserStore<IdentityUser>(context){
                DisposeContext = true
            };

            return new UserManager<IdentityUser>(userStore);
        };

But the problem occurs when I try to log in that I get "cannot contact server". I imagine that is because my UserStore has no way of knowing which are the User tables on my context. I'd hoped this is what the OnModelCreating code would do, but I'm hazy on this. I imagine UserStore is still looking for an "AspNetUsers" table, though I don't know where these names come from. I'm also uneasy about modifying the t4 template for my context - is this the way I'm supposed to derive from IdentityDbContext?

Any help greatly appreciated.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
see sharper
  • 11,505
  • 8
  • 46
  • 65
  • If you're happy with my answer could you, please, accept it? Cheers. – LeftyX Sep 17 '15 at 08:19
  • @see sharper any suggestion for my question http://stackoverflow.com/questions/36929767/asp-net-identity-entity-framework-database-first-approach-with-own-table-definti – SivaRajini May 02 '16 at 09:34

2 Answers2

21

Few steps to follow:

  • Install NuGet Package: Microsoft.AspNet.Identity.EntityFramework
  • Add a connection string to your web.config/app.config

Now you have to define your custom Database Context:

public class MyContext : IdentityDbContext
{
    public MyContext()
        : base(<connection string name>)
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<IdentityUser>()
            .ToTable("Users");

        modelBuilder.Entity<IdentityRole>()
            .ToTable("Roles");

        modelBuilder.Entity<IdentityUserRole>()
            .ToTable("UserRoles");

        modelBuilder.Entity<IdentityUserClaim>()
            .ToTable("UserClaims");

        modelBuilder.Entity<IdentityUserLogin>()
            .ToTable("UserLogins");
    }
}

As you can see I've used DbModelBuilder to map all the entities to a new tables.

  • Open NuGet Package Manager Console
  • Execute command Enable-Migrations

It will create a folder Migrations with the configuration file Configuration.cs.

It should look something like this:

internal sealed class Configuration : DbMigrationsConfiguration<ConsoleApplication1.Models.MyContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ConsoleApplication1.Models.MyContext context)
    {

    }
}

In the constructor change the property AutomaticMigrationsEnabled to true.

  • Open NuGet Package Manager Console
  • Execute command Update-Database

It should run the script to create the new tables.

You can customize your entities (and Ids) creating custom class for each interface defined.

public class MyUser : IdentityUser<string, MyUserLogin, MyUserRole, MyUserClaim>
{
}

Since you're using Owin you can define your UserStore:

public class MyUserStore: UserStore<MyUser, MyRole, string, MyUserLogin, MyUserRole, MyUserClaim>
{
    public MyUserStore(MyContext context)
        : base(context)
    {
    }
}

and your UserManager implementation:

public class ApplicationUserManager : UserManager<ASPNETIdentity2.Models.MyUser, string>
{
    public ApplicationUserManager(IUserStore<ASPNETIdentity2.Models.MyUser, string> store)
        : base(store)
    {

    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new MyUserStore(context.Get<MyContext>()));

        manager.UserValidator = new UserValidator<MyUser, string>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        manager.PasswordValidator = new PasswordValidator()
        {
            RequiredLength = 5,
            RequireNonLetterOrDigit = false,     // true
            // RequireDigit = true,
            RequireLowercase = false,
            RequireUppercase = false,
        };

        return (manager);
    }
}

And your Owin.Startup should look something like this:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.CreatePerOwinContext(MyContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    }
}

If you want to have a look at a custom implementation you can check my GitHub repository with a simple working solution on ASP.NET MVC.

UPDATE:

There's another project in that solution with a minimal setup; basically you only need to define your context (IdentityDbContext) if you only want to rename your tables.

The project can be found here.

LeftyX
  • 35,328
  • 21
  • 132
  • 193
  • Thank you very much for this info. My question is, once I have completed this, can I just get rid of the code-first stuff, as we aren't using CF in this project? – see sharper Jul 15 '14 at 22:43
  • @seesharper: I've updated my answer. Check the link in my github repo. – LeftyX Jul 16 '14 at 14:11
  • Thanks very much @LeftyX - it seems however that Identity 2 EF assumes Code First, which we don't use. Therefore I've had to adopt another solution. – see sharper Jul 18 '14 at 03:35
  • @LeftyX everything works as expected, but i keep getting the old AspNetUsers with one column (Id) whenever i do an Update-Database – Yehia A.Salam Jan 19 '15 at 00:33
  • @YehiaA.Salam: try to remove all the tables `EXEC sp_MSforeachtable @command1 = "DROP TABLE ?"` and run `Update-Database` again. – LeftyX Jan 19 '15 at 09:03
  • thanks, @LeftyX i was missing actual 'modelBuilder.Entity() .ToTable("Users");' I extended the Identity class – Yehia A.Salam Jan 19 '15 at 23:00
  • @LeftyX Since you have extended all the base classes you can just write public class MyContext : DbContext and there's no need to rely on identityDbContext . – Saber Mar 01 '16 at 12:16
  • @leftyx could you please look at my question http://stackoverflow.com/questions/36929767/asp-net-identity-entity-framework-database-first-approach-with-own-table-definti – SivaRajini May 02 '16 at 09:34
  • @SivaRajini: I had a look at your question and this answer should work for your problem as well. Am I wrong? – LeftyX May 02 '16 at 17:48
  • @LeftyX whether i need to add UserLogins and UserClaims table. because i dont have those tables and also Whether I need to maintain the same column name and datatype... example : in My user table i have user_id , login_id but in asp.netusers table having "Id","userName" fields respectively. – SivaRajini May 03 '16 at 04:19
  • @Leftyx whether i need to modify the user table column name"user_id" to "id" and login_id to "Username" and also is it necessary to have all the columns in asp.net users table to my user table (like securitystamp etc...). – SivaRajini May 03 '16 at 04:22
0

Identity 2 with Entity Framework assumes Code First. This project seems to do what I need: https://github.com/cbfrank/AspNet.Identity.EntityFramework

see sharper
  • 11,505
  • 8
  • 46
  • 65