I'm trying to extend the ApplicationUser class so that I can contain UserProfile information in a separate table. However I'm having trouble getting this to work and am getting an exception when I call the UserManager.CreateAsync
method in my AccountController.
Invalid column name 'UserProfileId'.
My Application User class
public class ApplicationUser : IdentityUser
{
[ForeignKey("UserProfileId")]
public virtual UserProfile UserProfile { get; set; }
public int UserProfileId { get; set; }
}
My User Profile class
public class UserProfile
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required, MaxLength(200)]
public string EmailAddress { get; set; }
[Required, MaxLength(50)]
public string FirstName { get; set; }
[Required, MaxLength(50)]
public string LastName { get; set; }
}
My first entity generated code migration
CreateTable(
"dbo.AspNetUsers",
c => new
{
Id = c.String(nullable: false, maxLength: 128),
UserName = c.String(),
PasswordHash = c.String(),
SecurityStamp = c.String(),
UserProfileId = c.Int(),
Discriminator = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.UserProfile", t => t.UserProfileId, cascadeDelete: true)
.Index(t => t.UserProfileId);
My code to create the new user on Registration
var user = Mapper.Map<ApplicationUser>(model);
var result = await UserManager.CreateAsync(user, model.Password);
With Automapping config of
Mapper.CreateMap<RegisterViewModel, ApplicationUser>()
.ForMember(dest => dest.UserProfile, opt => opt.MapFrom(v => Mapper.Map<RegisterViewModel, Data.Model.UserProfile>(v)));
Mapper.CreateMap<RegisterViewModel, Data.Model.UserProfile>()
.ForMember(dest => dest.FirstName, opt => opt.MapFrom(v => v.FirstName))
.ForMember(dest => dest.LastName, opt => opt.MapFrom(v => v.LastName))
.ForMember(dest => dest.EmailAddress, opt => opt.MapFrom(v => v.EmailAddress));
NOTE: I have tried removing the int UserProfileId
and this instead created a field called UserProfile_Id
which caused issues in and of itself.
Solved it. The problem was nothing to do with anything posted in my question. It ended up being because of my use of Dependency Injection causing the wrong DBContext being created and inserted into the AccountController.
What appears to be happening was because I did not have a DbContext mapped in my AutoFaq setup, the constructor used to create the UserStore was it's default. And in this case it appears that means creating a IdentityContext rather than my application DataContext class. However this context did not have the new UserProfile property hence it error'd out on UserProfileId.
I fixed this by adding a specific constructor parameter to my AutoFaq setup.
builder.RegisterType<Data.Model.DataContext>()
.As<IDataContext>()
.InstancePerHttpRequest();
// Added this here to ensure the context passed in is my DataContext
builder.RegisterType<UserStore<ApplicationUser>>()
.As<IUserStore<ApplicationUser>>()
.WithParameter((pi, ctx) => { return pi.Name == "context"; },
(pi, ctx) => { return ctx.Resolve<IDataContext>(); }
);
builder.RegisterType<UserManager<ApplicationUser>>().As<UserManager<ApplicationUser>>();
Just another possibility to save those who, like me had the correct constructor being hit. I had a method to create seed data in the database registered in my startup.cs (Core 2) this was querying the table I was trying to extend and caused the same error. Made sense when I found it I guess. Commenting out the lines while I ran add-migration was enough to get me past the issue.
Thanks, the accepted answer helped me. For anyone using Ninject, this is the code that I ended up with
Bind<IUserStore<ApplicationUser>>().ToMethod(
ctx =>
{
var dbContext = ApplicationDbContext.Create();
return new UserStore<ApplicationUser>(dbContext);
}
);
Bind<UserManager<ApplicationUser>>().ToSelf();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.