I have an ASP.NET Web API application which has two types of users — clients and drivers. Currently, I have methods in the client and driver controller for registering clients and drivers. I realised the correct way to do this is through the built-in authentication system via the ApplicationUser class. Basically, the whole thing is confusing me because for both of the user types I have different fields. Anyway, I have come up with two possible solutions, however, both of them don't sound like the correct way to achieve my goal.

1) Inherit from ApplicationUser

ApplicationUser.cs

public class ApplicationUser : IdentityUser
{
    [Column(TypeName = "datetime2")]
    public DateTime RegistrationDate { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
        return userIdentity;
    }
}

Client.cs

public class Client : ApplicationUser
{
}

Driver.cs

public class Driver: ApplicationUser
{
    private ICollection<Country> countriesOfOperation;

    public Driver()
    {
        this.countriesOfOperation = new HashSet<Country>();
    }

    [Column(TypeName = "datetime2")]
    public DateTime DateOfBirth { get; set; }

    [MaxLength(250)]
    public string AboutMe { get; set; }

    public Genders Gender { get; set; }

    public virtual ICollection<Country> CountriesOfOperation
    {
        get { return this.countriesOfOperation; }
        set { this.countriesOfOperation = value; }
    }
}

This means that I have to create register methods into the AccountController like this:

[AllowAnonymous]
[Route("Clients/register")]
public async Task<IHttpActionResult> RegisterClient(ClientRegisterBindingModel model)
{
    var user = new Client()
    {
        UserName = model.Email,
        Email = model.Email,
        RegistrationDate = DateTime.Now
    };

    IdentityResult result = await UserManager.CreateAsync(user, model.Password);

    if (!result.Succeeded)
    {
        return GetErrorResult(result);
    }

    return Ok();
}

Same thing goes for the driver class. Surely, the inheritance reuses stuff like UserName, Email, PasswordHash etc., but it also means that I have to create methods like the register one for every type of user I add. Which makes the account management pain in the ass.

2) Keeping clients and drivers in separate tables by having a field that references an ApplicationUser

public class Client
{
    public string FirstName { get; set; }

    public ApplicationUser Account { get; set; }
}

This seems a bit better, but to access the username of a client I have to do something like clientInstance.Account.UserName, which still doesn't seem elegant enough.

I'm pretty new to the technology and I haven't explored all of its features, so I'm likely missing something fairly obvious. Thanks in advance.

Related posts

Recent Viewed