2014-01-06 25 views
6

對於泛型類型的響應對象的文檔,我遇到Swagger的ServiceStack實現問題。強類型的響應對象被正確記錄並顯示,但是一旦泛型類型的對象被用作響應,文檔就不準確並且具有誤導性。在Swagger(ServiceStack)中未準確記錄泛型類型的響應對象

請求DTO

[Route("https://stackoverflow.com/users/{UserId}", "GET", Summary = "Get a specific User Profile")] 
public class GetUser : IReturn<ServiceResponse<UserProfile>> 
{ 
    [ApiMember(Description = "User Id", ParameterType = "path", IsRequired = true)] 
    public int UserId { get; set; } 
} 

響應DTO

public class ServiceResponse<T> : IServiceResponse<T> 
{ 
    public IList<string> Errors { get; set; } 
    public bool Successful { get; set; } 
    public string Message { get; set; } 
    public string StackTrace { get; set; } 
    public T Data { get; set; } 

    public ServiceResponse() 
    { 
     Errors = new List<string>(); 
    } 
} 

響應DTO類型

public class UserProfile : RavenDocument 
{ 
    public UserProfile() 
    { 
     Races = new List<UserRace>(); 
     Workouts = new List<Workout>(); 
    } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string DisplayName { get; set; } 
    public DateTime? BirthDate { get; set; } 
    public Gender? Gender { get; set; } 
    public string UltracartPassword { get; set; } 
    public string UltracartCartId { get; set; } 

    [UniqueConstraint] 
    public string Email { get; set; } 

    public string ImageUrl { get; set; } 

    public FacebookUserInfo FacebookData { get; set; } 
    public GoogleUserInfo GoogleData { get; set; } 

    public DateTime CreatedOn { get; set; } 
    public DateTime? LastUpdated { get; set; } 
    public UserAddress ShippingAddress { get; set; } 
    public UserAddress BillingAddress { get; set; } 
    public IList<UserRace> Races { get; set; } 
    public IList<Workout> Workouts { get; set; } 
} 

示例s很直截了當。真的沒什麼哈克或聰明的事情,但是這是樣本文件,我從揚鞭走出箱子:

Swagger Example

正如你所看到的,通用的類型不正確記錄和一些其他類型的改爲使用。由於我對所有回覆都使用了同樣的ServiceResponse包裝,所以這一切都在發生。

回答

2

正如您發現的那樣,ServiceStack swagger插件目前不會嘗試乾淨地處理泛型類型。應該更好地工作的一個簡單替代方法是製作泛型類型的具體子類。例如:

public class UserProfileResponse : ServiceResponse<UserProfile> { ... } 

public class GetUser : IReturn<UserProfileResponse> ... 

這應該由Swagger正確處理。

我發現泛型類型並不總是非常適合於ServiceStack DTO。您將在StackOverflow上找到許多討論(例如here,herehere),討論這一點,以及具體類型和通常避免繼承的原因對於ServiceStack DTO是個好主意。

它需要努力克服應用DRY原則來請求/響應DTO的誘惑。我想到的方式是,泛型和繼承是語言特性,以通用的,可重用的方式實現算法,其中泛型方法或基類不需要知道具體類型的細節。儘管DTO可能表面上具有看起來像繼承或泛型機會的共同結構,但在這種情況下,每個DTO的實現和語義對於每個具體用法都不相同,因此每個請求/響應消息的細節都應該明確定義。

+2

感謝您的回覆。在ServiceStack DTOs中反對使用泛型和繼承的建議聽起來很清楚。但是,我們正在嘗試爲我們的Web /移動客戶端使用通用的Domain/DTO庫,以在反序列化之後促進類型安全。在這樣做的時候,我試圖擺脫爲每個域類型創建一個新的響應DTO,而是使用泛型來指定泛型響應將包含的域類型。 最終,它是一個時間/代碼節省措施,可能會讓我們在後面談到文檔。 再次感謝! –