I know this description is a bit lengthy, but its easy to follow. I have created a custom storage provider which uses Dapper as a replacement for Entity Framework. To do so I've created a class library called AspNet.Identity.Dapper. The Web app simply adds a reference to this class library to replace EF.
Inside the class library is this code:
In creating the custom provider I implemented my own UserStore. The UserStore implements all the interfaces. Here is the definition:
public class UserStore<TUser> : IUserLoginStore<TUser,int>,
IUserClaimStore<TUser,int>,
IUserRoleStore<TUser,int>,
IUserPasswordStore<TUser,int>,
IUserSecurityStampStore<TUser,int>,
IQueryableUserStore<TUser,int>,
IUserEmailStore<TUser,int>,
IUserPhoneNumberStore<TUser,int>,
IUserTwoFactorStore<TUser, int>,
IUserLockoutStore<TUser, int>,
IUserStore<TUser,int>,
IDisposable
where TUser : IdentityMember
Notice the constraint on the generic type
where TUser : IdentityMember
The UserStore makes calls to UserTable defined as:
public void Insert(TUser member)
{...}
The call is made by the Identity code so I cannot change the definition. To customize the class used in the web app to add extra custom fields, one only need add fields to the AppMember class which inherits from the IdentiyUser class. The below code snippet is from the web app which consumes the class library. Notice I simply add the Profile field to the class.
This code is from the consuming Web app:
public class AppMember : IdentityMember
{
public Profile MemberProfile { get; set; }
}
Inside the AccountController Resger method is this code:
await SignInManager.SignInAsync(AppMember, isPersistent: false, rememberBrowser: false);
Here I simply populate the Profile field before the AppMember gets sent on its way to the UserStore.
NOW, HERE IS THE PROBLEM:
I cannot access the additional fields of AppMember at design time because it lives inside its own library and it doesn't know about AppMember. AppMember is defined in the consuming web app.
Inside the UserTable class in the external class library is the Insert method as defined above. Notice it takes a TUser member parameeter. At run time, this resolves to be of type AppMember per above as it should. However, at design time, it resolves to IdentityMember because of the constraint defined above. Hence, I cannot access the Profile field at design time so I can't persist them to the database. If I try this
member.Profile.fieldName
I get a compile error because it doesn't know about Profile. However at run time its there. I checked with the debugger and the type at run time is AppMember as it should be.
I would prefer to not add all the "extra fields" to the IdentityModel class in the Dapper library but at this point I don't know any other way around it. So I'm presenting this to the much smarter and more experienced developers than I in the hope I'm missing something and there is a way to accomplish this.
Any help in resolving this matter would be greatly appreciated! Thank you!