【问题标题】:Generic-typed response object not accurately documented in Swagger (ServiceStack)Swagger (ServiceStack) 中未准确记录的泛型响应对象
【发布时间】:2014-01-06 14:26:54
【问题描述】:

关于泛型类型响应对象的文档,我对 Swagger 的 ServiceStack 实现有疑问。强类型的响应对象被正确记录和显示,但是一旦使用泛型类型的对象作为响应,文档就不准确且具有误导性。

请求 DTO

[Route("/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; }
}

这些例子非常简单。没有什么真正的 hacky 或聪明的事情发生,但这是我从 Swagger 获得的开箱即用的示例文档:

如您所见,泛型类型没有正确记录,而是使用了其他类型。由于我对所有响应都使用相同的 ServiceResponse 包装器,因此这种情况正在全面发生。

【问题讨论】:

    标签: servicestack swagger swagger-ui


    【解决方案1】:

    正如您所发现的,ServiceStack swagger 插件目前并未尝试干净地处理泛型类型。一个更好的简单替代方法是创建泛型类型的具体子类。例如:

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

    这应该由 Swagger 妥善处理。

    我发现泛型类型并不总是非常适合 ServiceStack DTO。您会在 StackOverflow 上找到许多讨论(例如 hereherehere)讨论这个问题,以及具体类型和通常避免继承对于 ServiceStack DTO 来说是一个好主意的原因。

    克服将 DRY 原则应用于请求/响应 DTO 的诱惑需要付出努力。我的想法是泛型和继承是有助于以通用、可重用的方式实现算法的语言特性,其中泛型方法或基类不需要了解具体类型的细节。虽然 DTO 表面上可能具有看起来像是继承或泛型机会的通用结构,但在这种情况下,每个 DTO 的实现和语义对于每个具体用法都不同,因此每个请求/响应消息的细节都值得明确定义。

    【讨论】:

    • 感谢您的回复。反对在 ServiceStack DTO 中使用泛型和继承的建议是合理且易于理解的。但是,我们正在尝试为我们的 Web/移动客户端使用公共域/DTO 库,以促进反序列化后的类型安全。在这样做时,我试图避免为每个将返回的域类型创建一个新的响应 DTO,而是使用泛型来指定泛型响应将包含的域类型。归根结底,这是一种节省时间/代码的措施,在文档方面可能会让我们陷入困境。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 2020-04-30
    • 2018-08-24
    相关资源
    最近更新 更多