2015-11-13 61 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字符串。 –