extend asp.net identity user cause database error - c#

I tried to extend the asp.net identity user with a "Name" property, I therefore followed the description in this post How to extend available properties of User.Identity
But after I did that and tried to login I get this error "The model backing the 'ApplicationDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database"
Can I fix this or can you only extend the asp.net ueser identity before the database is created the first time?

Based on Asp.Net template database will generate the bellow structure:
In order to extend asp.net identity user and keep the things simple, please update IdentityModels.cs with following code:
//CODE
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Data.Entity.Migrations;
namespace WebApplication.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
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 class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, ApplicationDbContextConfiguration>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityRole>().ToTable("AspNetRoles");
modelBuilder.Entity<IdentityUserRole>().ToTable("AspNetUserRoles");
modelBuilder.Entity<IdentityUserLogin>().ToTable("AspNetUserLogins");
modelBuilder.Entity<IdentityUserClaim>().ToTable("AspNetUserClaims");
modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers");
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
internal sealed class ApplicationDbContextConfiguration : DbMigrationsConfiguration<ApplicationDbContext>
{
public ApplicationDbContextConfiguration()
{
ContextKey = "WebApplication.Models.ApplicationDbContext"; //Retrieved from the database table dbo.__MigrationHistory
#if DEBUG
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
#else
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = false;
#endif
}
protected override void Seed(ApplicationDbContext context)
{
base.Seed(context);
}
}
}
The output is:
PS: You can rename default names for asp.net generated tables, personally I prefer to remove AspNet suffix

Related

Error when trying to add roles in seed method - ASP.NET MVC 5

This is my first ever project in ASP.NET MVC 5 and C# in general. I'm trying to make a simple CRM web app.
When I try to set roles in my seed method I get the following error after executing the Update-Database command:
The entity type IdentityRole is not part of the model for the current context.
I've searched a lot but didn't find a solution yet.
Configuration.cs
using System.Collections.Generic;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using simpleCRM.Models;
namespace simpleCRM.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<simpleCRM.DAL.crmContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "simpleCRM.DAL.crmContext";
}
protected override void Seed(simpleCRM.DAL.crmContext context) //Takes our context as input
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
//Creating the admin role
if (!roleManager.RoleExists("Director"))
{
//Admin role
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole("Director");
roleManager.Create(role);
}
context.SaveChanges();
}
}
crmContext.cs
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using simpleCRM.Models;
/*A class that coordinates the Entity Framework functionality for a given data model.
It derives from System.Data.Entity.DbContext class*/
namespace simpleCRM.DAL
{
public class crmContext: DbContext
{
public crmContext() : base("crmContext")//Passing the connection string to the constructor
{
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Call> Calls { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
}
}
}
What might be the cause of the error?

Access dbcontext at startup

.NET MVC5 Application using Identity 2.
I need to call a method of my service at application startup, but the method needs to access the database. where and how can I do this?
IdentityModel.cs is the place needs modification
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
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 class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
instead of default connection, you can create multiple environment variables. Hope this answered your question

Issues with DbContexts causing Errors

I currently have multiple projects with multiple DbContexts:
Projects (DbContext):
Model
DataAccessLayer (EntityContext)
ServiceLayer
Web (IdentityContext)
I have a Model in the Model's project called Department that is created by the EntityContext and i reference to it in the ApplicationUser.cs in the Web Project.
When the IdentityContext is trying to create the AspNet Tables it also tries to recreate the Department Table and i get the following error:
"There is already an object named 'Departments' in the database."
Here's my Identity Files:
The IdentityContext is my Web Project:
ApplicationDbContext.cs
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("EntityContext", throwIfV1Schema: false)
{
Configuration.LazyLoadingEnabled = false;
Configuration.AutoDetectChangesEnabled = false;
Configuration.ProxyCreationEnabled = false;
Configuration.ValidateOnSaveEnabled = false;
}
static ApplicationDbContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, ApplicationDbInitializer>());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
ApplicationDbInitializer.cs
public class ApplicationDbInitializer : DbMigrationsConfiguration<ApplicationDbContext>
{
public ApplicationDbInitializer()
{
AutomaticMigrationsEnabled = false;
#if DEBUG
AutomaticMigrationDataLossAllowed = true;
AutomaticMigrationsEnabled = true;
#endif
}
protected override void Seed(ApplicationDbContext context)
{
base.Seed(context);
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
/// <summary>
/// Linked Department Id
/// </summary>
public Guid? DepartmentId { get; set; }
/// <summary>
/// Linked Department Object
/// </summary>
[ForeignKey("DepartmentId")]
public virtual Department Department { get; set; }
}
I then commented out the "public DbSet Department { get; set; }" in the EntityContext and now it builds but when i try to access it i get this error:
"The entity type Department is not part of the model for the current context."
I understand both errors, but i can't figure out how to get them to be on the same context, as they are in different projects.
Traditionally in a situation like this I would rather you make your Context inside of the DataAccessLayer be the IdentityContext. Since you have ties between the IdentityContext and that particular context anyway, it gives you a single context to represent your application and doesn't introduce a shared context issue.
This would result in removing the DBContext from your web project, and changing the base class of your Context inside of the DataAccessLayer to become IdentityDbContext<ApplicationUser> rather than the current DbContext base class.
Most likely, this will result in you moving a few entities into the lower DLL, but again it makes that DLL more representative of the entire solution.

ApplicationDbContext.OnModelCreating(ModelBuilder): no suitable method found to override

I am trying to use code first migration approach(genrate database from code). but facing error. here is my code
using Microsoft.AspNet.Identity.EntityFramework;
namespace IMChatApp.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
public System.Data.Entity.DbSet<JustDoIt.Models.user> users { get; set; }
}
}
According to the documentation, the OnModelCreating method takes a DbModelBuilder, not a ModelBuilder.

Why dont my tables get created with this MVC5 configuration inheriting from IdentityDbContext

public class MyContext: IdentityDbContext<ApplicationUser>
{
public MyContext()
: base("MyContext", throwIfV1Schema: false)
{
}
public static MyContext Create()
{
return new MyContext();
}
public System.Data.Entity.DbSet<xxxx> xxxxx { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Startup.Auth:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(MyContext.Create); // ALTERED THIS
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); // ALTERED THIS
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
ApplicationUser:
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;
}
}
// this is the old code, no longer referenced in startup.auth:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("MyContext", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
So basically, Ive set my new context to inherit from IdentityDbContext, and replaced any reference of the old ApplicationDbContext with my new one. It creates the Identity tables, but none of my DbSet tables I specify (omitted, left one crossed out for sample
I'm just guessing here because I can't see your code, but I'm reasonably sure I'm correct. When you start a new project, you have to enable migrations. How this works is that it inspects your project for objects derived from DbContext and then creates a Migrations folder with a Configuration.cs file inside. This file explicitly references the context that is used for migrations. If you do this with more than one object derived from DbContext in your project (here, you have two, MyContext and ApplicationDbContext), it will fuss at you and tell you that you need to specify which one to use. This probably didn't happen because you had previously enabled migrations with the generated context from Identity, and only later added your own context.
Long and short, check this configuration file and change any offending references there. Or, you can just delete the Migrations folder completely and run Enable-Migrations again in the package manager console, making sure to specify MyContext as the context to be used.
Annoyingly small changes:
no throwIfV1Schema: false
public class MyContext: IdentityDbContext<ApplicationUser>
{
public MyContext() : base("MyContext")
{
}
public static MyContextCreate()
{
return new MyContext();
}
public System.Data.Entity.DbSet<xxx> xxx{ get; set; }
}

Categories

Resources