2014-01-06 6 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; } 
} 

例かなりストレートです。本当にハックまたは起こって巧妙な何も、しかし、これは私が箱から出して闊歩から取得したサンプルのドキュメントではありません:あなたが見ることができるように

Swagger Example

は、ジェネリック型が正しく文書化されておらず、他のいくつかのタイプがあります代わりに使用されます。すべての回答に対して同じServiceResponseラッパーを使用しているので、これは全面的に起こっています。

答えて

2

あなたが見つけたように、ServiceStack swaggerプラグインは現在、ジェネリック型をきれいに処理しようとしません。よりうまくいくはずの簡単な方法は、ジェネリック型の具体的なサブクラスを作成することです。例:

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

public class GetUser : IReturn<UserProfileResponse> ... 

これはSwaggerによって正しく処理されます。

ジェネリック型が常にServiceStack DTOに適しているとは限りません。これについて議論する多くの議論(例えばherehereおよびhere)がStackOverflowにあります。具体的なタイプと一般的な継承を避ける理由は、ServiceStack DTOにとっては良い考えです。

DTOを要求/応答するためにDRYの原則を適用しようとする誘惑を克服するために努力しています。私が考えているのは、ジェネリックメソッドやベースクラスは、具体的な型の詳細を知る必要がない、汎用的で再利用可能な方法でアルゴリズムの実装を容易にする言語機能です。 DTOは、継承またはジェネリックの機会のように見える共通の構造を表面的に有することがあるが、この場合、各DTOの実装およびセマンティクスは、具体的な使用ごとに異なるため、各要求/応答メッセージの詳細を明示的に定義する必要がある。

+2

お返事ありがとうございます。 ServiceStack DTOでのジェネリックおよび継承の使用に関するアドバイスは、妥当であり、理解されています。しかし、私たちは、Web /モバイルクライアントに共通のDomain/DTOライブラリを使用して、デシリアライズ後の型の安全性を促進しようとしています。そうすることで、私は、各ドメインタイプの新しい応答DTOを作成することから離れようとしていましたが、一般的な応答に含まれるドメインタイプを指定するためにジェネリックを使用しました。 最終的には、ドキュメンテーションに関しては、時間を節約してコードを保存していたかもしれません。 もう一度おねがいします! –

関連する問題