4

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!

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
sfuptown
  • 277
  • 1
  • 5
  • 14
  • Why insist on an open store class? Are you sure the open type `TUser` is necessary there? Are you going to yet derive from it and provide a conrete type in the derived class? – Wiktor Zychla Sep 02 '14 at 21:26
  • TUser is the generic parameter and is I can't change it as its bound to the interface. – sfuptown Sep 02 '14 at 23:27
  • Inside the Insert method in the UserTable class I added this 1 line. dynamic m = member; Admittedly its a hack, but it does let me get to the new properties during design time and the compiler accepts it because its resolved at run time. I'm hoping there is a better solution, but have yet to find it. – sfuptown Sep 02 '14 at 23:27
  • 1
    Have you published the full code of your implementation with Dapper? I would be interested in using it in my own project. – Ryan Rodemoyer Sep 25 '14 at 14:29
  • 1
    Ryan, you can find it here. https://github.com/whisperdancer/AspNet.Identity.Dapper – sfuptown Sep 29 '14 at 18:56
  • Haha I started work on my own version and it's to the point where a user can register and sign in with Dapper as the backend - no EF at all. You can find it here. https://github.com/ryanrodemoyer/AltProvidersForAspNetIdentity2 – Ryan Rodemoyer Sep 30 '14 at 13:24
  • 2
    @sfuptown - why the extra layer of code to write records for the user (and other) tables? Why not just manage them from the UserStore? What was your design need to do that? ie - you have the class UserTable to wrap up all DB access to the user's table represented by your IdentityUser class; why not just do that in UserStore? In other words, why allow separate access to your security mechanism datastore? – Robert Achmann Oct 28 '14 at 12:57

0 Answers0