2015-11-13 59 views
0

我有一个ASP.NET Web API应用程序,它有两种类型的用户 - 客户端和驱动程序。目前,我在客户端和驱动程序控制器中有注册客户端和驱动程序的方法。我意识到正确的做法是通过内置的认证系统通过ApplicationUser类。基本上,整个事情让我感到困惑,因为对于这两种用户类型我都有不同的领域。无论如何,我已经提出了两种可能的解决方案,但是,这两种解决方案听起来都不像实现我的目标的正确方法。ASP.NET Web API正确的方式有两种类型的ApplicationUser

1)继承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; } 
    } 
} 

这意味着,我必须创建注册方法到帐户控制器是这样的:

[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(); 
} 

同样的事情去驱动类。当然,继承重用像UserName,Email,PasswordHash等东西,但这也意味着我必须为每种类型的用户添加注册之类的方法。这使得帐户管理在屁股上很痛苦。

2)具有引用字段保持在单独的表客户端和驱动一个ApplicationUser

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

    public ApplicationUser Account { get; set; } 
} 

这似乎有点好转,但访问客户端我要像做clientInstance.Account.UserName的用户名,这仍然不够优雅。

我对这项技术非常陌生,而且我还没有探索过它的所有功能,所以我很可能错过了一些相当明显的东西。提前致谢。

+0

保持客户端和驱动在同一个表只是有不同的帐户ID为他们也许有一个叫'Group'和手动列创建它们拥有所有的客户端为第1组和所有驱动程序作为第2组 – MethodMan

+0

@MethodMan,止跌”把它们放在同一个表中留下太多未使用的列?例如,驱动程序类具有客户端不具有的3-4个字段,这意味着它们对于客户端行必须为NULL。 – arnaudoff

+0

如果你看到一个数据库布局的例子,你将会非常高兴,你可以使用2个表格并构建一个连接查询,我认为你正在使得方法比需要的更困难。有很多方法来为这个猫皮肤 – MethodMan

回答

1

只需为所有类型的用户使用一张表。所有用户注册都是一样的。当创建新用户时,您将在其中添加更多详细信息。

Schema: 
int ID 
int UserType 
nvarchar Details 
etc... 

Entity: 
public class User 
{ 
    public int ID {get;set;} 
    public int UserType {get;set;} 
    public string Email{get;set;} 
    public string Password{get;set;} 
    public string Details {get;set;} 
} 

在注册过程中,他们得到相同的处理。当创建新用户时,您将添加各种详细信息。

//driver 
var user = new User() 
{ 
    Details = { 
     TruckID = 5, 
     SomeOtherDetails = "Whatever" 
    }.ToJson() //fake extention method, just convert to jsons string 
}; 

//client 
var user = new User() 
{ 
    Details = { 
     ClientNumber = 44 
    }.ToJson() 
}; 

如果这些需要与后来只得到用户,然后反序列化的细节了基于用户类型不同类型的加工。

var user = GetSomeuser(1); 
var truckID = user.Details.FromJson<DriveDetails>().TruckID; //fake extension method to deserialize json string back to object 

public class DriverDetails 
{ 
    pubic int TruckID... 
    public string SomeOtherDetails... 
} 
+0

答案的第一部分是向你展示你“如何”处理它,但不建议。用户应该只是用户,他们注册的方式相同。如果某种用户需要不同的细节,只需将它们存储为文档数据库即可,并根据它是哪种类型的用户将其反序列化。 –

+0

基本上,你的想法是有一个单独的表的附加细节,并有一个外键?例如,我让用户Foo具有默认帐户属性作为ApplicationUser,但也具有ApplicationUser类型的列和另一列是包含我需要用于特定类型用户的额外列的表的外键? – arnaudoff

+0

那么这是一种方式,但首选的方法是只有一个表。所有额外的细节将进入该字段的json字符串。 –