Swashbuckle.aspnetcore: Limit the depth of properties documented by Swashbuckle for [ProducesResponseType] annotations

Created on 27 Feb 2018  路  4Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

I put up a stackoverflow question with no luck, so hoping someone can point me in the right direction :)
https://stackoverflow.com/questions/48987127/limit-the-depth-of-properties-documented-by-swashbuckle-for-producesresponsetyp

I am annotating like this;

// DELETE: api/MyType
    /// <summary>
    /// Deletes a MyType with specified ID
    /// </summary>
    /// <param name="key">The ID of the MyType to delete</param>
    /// <returns>The data for the deleted MyType</returns>
    [HttpDelete]
    [ProducesResponseType(typeof(MyType), 200)]

Which is fine, but MyType has many reference properties which in turn have referenced properties etc. This results in a massive document like this (but WAY bigger)

  "IsAvlOverride": true,
  "Notes": "string",
  "DateRejected": "2018-02-26T21:53:26.127Z",
  "GeometryType": 0,
  "PrimaryTagId": 0,
  "OptimisticLockField": 0,
  "Atplot": [
    {
      "UniqueId": "string",
      "Hrid": "string",
      "CreatedBy": 0,
      "CreatedOn": "2018-02-26T21:53:26.127Z",
      "ModifiedBy": 0,
      "ModifiedOn": "2018-02-26T21:53:26.127Z",
      "AtpLotId": 0,
      "AtpId": 0,
      "LotId": 0,
      "ItemInspect": "string",
      "DateInspect": "2018-02-26T21:53:26.127Z",
      "TimeInspect": "2018-02-26T21:53:26.127Z",
      "DateApproved": "2018-02-26T21:53:26.127Z",
      "ApprovedById": 0,
      "ApprovalComments": "string",
      "OptimisticLockField": 0,
      "Approval": [
        {
          "UniqueId": "string",
          "Hrid": "string",
          "CreatedBy": 0,
          "CreatedOn": "2018-02-26T21:53:26.127Z",
          "ModifiedBy": 0,
          "ModifiedOn": "2018-02-26T21:53:26.127Z",
          "ApprovalId": 0,
          "ApprovalItemTypeId": 0,
          "ApprovalSubtypeId": 0,
          "RequestToId": 0,
          "RequestById": 0,
          "RequestText": "string",
          "RequestDate": "2018-02-26T21:53:26.127Z",
          "RequiredDate": "2018-02-26T21:53:26.127Z",
          "EmailDate": "2018-02-26T21:53:26.127Z",
          "ResponseDate": "2018-02-26T21:53:26.127Z",
          "ResponseText": "string",
          "ApprovalStatusTypeId": 0,
          "ProjectId": 0,
          "CloseOutDate": "2018-02-26T21:53:26.127Z",
          etc...

How can I create a operation/schema/document filter that limits the depth of recursion to just the top level, and just uses the type name for reference properties?

e.g.

  "IsAvlOverride": true,
  "Notes": "string",
  "DateRejected": "2018-02-26T21:53:26.127Z",
  "GeometryType": 0,
  "PrimaryTagId": 0,
  "OptimisticLockField": 0,
  "Atplot": [Atplot_object]

Most helpful comment

@domaindrivendev
Is it possible to limit the depth of generated examples now, or at least disable examples (for a particular endpoint maybe)?
I have a problem with swagger for an OData endpoint. The controller's action returns IQueryable, so it would be nice to use the real entity in [ProducesResponseType] to avoid code duplication.
OData allows limiting the expanding of nested collections, it's 2 by default. So the whole $expand feature is pretty secure. The only problem is to document it properly in Swagger: the generated example describes the whole database because of navigation properties in the entity, making the entire JSON cumbersome and almost unusable.

All 4 comments

Are you referring to the Swagger JSON document, or the example/model that's displayed in the swagger-ui?

If it's the latter, you have some options. Your example isn't even valid JSON, so that's clearly not possible. But, you can switch to "Model" mode, which shows a model description instead of an example, and you can also limit the expand depth for that model description:

app.UseSwaggerUI(c =>
{
    c.DefaultModelRendering(ModelRendering.Model);
    c.DefaultModelExpandDepth(1); 
});

Ah sorry for no being specific - the output was just a copy of the data shown in the swagger UI as the output for the method - not the JSON itself.

Although your suggestion makes the UI much better and is a definite improvement, I want to achieve the same result but without including the objects in the JSON itself. The JSON is already 160kb and will get much bigger - it is a really large schema. I am finding that the UI can take a while to update for methods with large output models

Example JSON at https://pastebin.com/VLr5guYX

By design, Swashbuckle treats the code as truth! So, it documents the entire API surface area, including all serializable properties on models. If your API surface area is too complex to document, then I might contend that it's going to be difficult to use, and might encourage a simpler design.

Of course it's not my place to dictate how you design your API but I will say that SB's fundamental goal is to automatically document API's based on the surface area that can be inferred from code - routes, controllers, actions methods and models. If you find you need to start fighting this, then it may not be the right tool for your specific use-case.

With all that said, a final suggestion would be to wire up a DocumentFilter (see readme) that clears the entire Definitions dictionary from the Swagger document before it's returned. I believe this will cause only the model names to be displayed, in other words a depth of 0. You _could_ smarten up the implementation further to only remove definitions that are displayed at a depth of 1 or 2 or beyond but that would require some complex traversing through the rest of the doc to figure that out.

@domaindrivendev
Is it possible to limit the depth of generated examples now, or at least disable examples (for a particular endpoint maybe)?
I have a problem with swagger for an OData endpoint. The controller's action returns IQueryable, so it would be nice to use the real entity in [ProducesResponseType] to avoid code duplication.
OData allows limiting the expanding of nested collections, it's 2 by default. So the whole $expand feature is pretty secure. The only problem is to document it properly in Swagger: the generated example describes the whole database because of navigation properties in the entity, making the entire JSON cumbersome and almost unusable.

Was this page helpful?
0 / 5 - 0 ratings