Search code examples
asp.net-mvcasp.net-membershipmembership-provider

ASP.NET Membership: Custom Profile Inheritance


I'm using ASP.NET MVC4, I've setup a custom profile class as described in this article about universal membership providers

public class CustomProfile : ProfileBase
{
    public DateTime? Birthdate
    {
        get { return this["Birthdate"] as DateTime?; }
        set { this["Birthdate"] = value; }
    }

    public static CustomProfile GetUserProfile(string username)
    {
        return Create(username) as CustomProfile;
    }

    public static CustomProfile GetUserProfile()
    {
        var user = Membership.GetUser();
        if (user == null) 
            return null;

        return Create(user.UserName) as CustomProfile;
    }
}

I've also updated the entry for the profile definition on web.config:

<profile defaultProvider="DefaultProfileProvider" inherits="MembershipTestsV3.Models.CustomProfile">
  <providers>
    <add name="DefaultProfileProvider" 
         type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
         connectionStringName="DefaultConnection" 
         applicationName="MyAppName" />
  </providers>
</profile>

This means I can instantiate my custom profile object like this whenever I want:

var customProfile = HttpContext.Profile as CustomProfile;

Now, I wish to have many types of profiles that inherit from this base; Such as AdminUserProfile, or SupervisorProfile:

public class SupervisorProfile : CustomProfile
{
    public string Department
    {
        get { return this["Department"] as string; }
        set { this["Department"] = value; }
    }
}

But, every time I try to cast the object I get a null reference exception:

var customProfile = HttpContext.Profile as SupervisorProfile;

I know that at the database level the profile will just save all related columns on the same table, I just want to have the properties organized on the service layer. Is there a way to achieve this?


Solution

  • It's not possible inside the ProviderModel, but you can achieve it if you build a layer around it. You could go several ways:

    • Save the related information in another table and save a reference to that information inside the profile. Then you can just keep a simple profile class and use a repository or another related class to get the extra information (which could be a base type with sub types). This would be favouring object composition over inheritance.
    • Keep a simple profile-class which has all the properties. Instead of getting the profile directly from the HttpContext, you could build a layer (factory if you will) around it, that inspects the instance and returns a different type, depending on the values inside the profile