I already have DB and need to add ASP.NET Identity. My AspNetUser class:
public partial class AspNetUser
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AspNetUser()
{
AspNetUserClaims = new HashSet<AspNetUserClaim>();
AspNetUserLogins = new HashSet<AspNetUserLogin>();
AspNetRoles = new HashSet<AspNetRole>();
}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public int? CompanyId { get; set; }
public string FullName { get; set; }
[Required]
[StringLength(128)]
public string Discriminator { get; set; }
public string SMSnumber { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
then my ApplicationDbContext context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MainContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
connection string:
<add name="MainContext" connectionString="data source=server;initial catalog=3md_maindb_remote;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public int CompanyId { get; set; }
public string SMSnumber { get; set; }
public string FullName { get; set; }
}
ApplicationUserManager:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
when I try to login, I get an error:
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'Email'. Invalid column name 'EmailConfirmed'. Invalid column name 'PhoneNumber'. Invalid column name 'PhoneNumberConfirmed'. Invalid column name 'TwoFactorEnabled'. Invalid column name 'LockoutEndDateUtc'. Invalid column name 'LockoutEnabled'. Invalid column name 'AccessFailedCount'.
Also, I have MainContext:
public partial class MainContext : DbContext
{
public MainContext()
: base("name=MainContext")
{
}
public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
as I understand, I need to use my MainContext instead of ApplicationDbContext (with my schema) , but don't understand how...
You can use multiple contexts on the same database. Out of the box the Identity Context is set to go. If you don't need to change it then don't. Use the Identity tables for Identity only.
You don't need to define the tables in the Identity Context. Just add the ApplicationDbContext. You can use the same connectionstring as for your MainContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("name=MainContext")
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
You really shouldn't add all your tables to the IdentityContext as that is not the place where they should be. Though the tables may be in the same database, the two contexts have nothing to do with eachother.
Keep you own tables in MainContext and do not relate beyond contexts, other than a column where you can reference (value only, not a database reference) the IdentityUser to your MainContext.User. Remove the AspNet... tables from MainContext.
You cannot use the class AspNetUser. So you may as well remove this. Use the ApplicationUser class instead. To overcome the problem of missing fields use this:
public class ApplicationUser : IdentityUser
{
[NotMapped]
public override bool EmailConfirmed { get => base.EmailConfirmed; set => base.EmailConfirmed = value; }
// etc.
}
This will ignore the missing columns. Keep in mind that the properties exist in the code and will have default values. Though I do not think your code is actually going to depend on these properties.
In case the MainContext gives you trouble, you can create your own context using the same entity objects. You can create multiple contexts on the same database, including used tables only, even if you use a seperate assembly.