How do you correctly set Swagger examples in ASP.NET Core?

Viewed 644

My goal:

To correctly set the request examples in the OpenApi JSON document on only the endpoints I annotate with SwaggerRequestExample and not the endpoint response or other endpoints lacking this attribute.

Expected Result:

"post": {
    "tags": [
      "Address"
    ],
    "requestBody": {
      "content": {
        },
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Address"
          },
          "example": {"id":"995ace6e-33d5-4efd-860e-b653fef60dad","binaryAddress":246,"distance":123}
        }
        }
      }
    },
    "responses": {
      "200": {
        "description": "Success",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Address"
            }
          }
          }
        }
      }

Actual Result:

"post": {
    "tags": [
      "Address"
    ],
    "requestBody": {
      "content": {
        },
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Address"
          },
          "example": {"id":"995ace6e-33d5-4efd-860e-b653fef60dad","binaryAddress":246,"distance":123}
        }
        }
      }
    },
    "responses": {
      "200": {
        "description": "Success",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Address"
            },
            "example": {"id":"a04c827c-5e29-4940-8bee-89f8e07af5a8","binaryAddress":246,"distance":123}
          }
          }
        }
      }

Error Messages:

I haven't encountered any error messages.

What I've tried:

I've tried several startup and controller attribute configurations to try and get the expected behavior, but have been unable to get the expected result. This is the configuration I expect to work, but unfortunately is not:

Startup.cs snippet

services.AddSwaggerGen(options =>
{
    options.MapType<ushort>(() => OpenApiSchemaFactory.MapInteger(typeof(ushort)));
});
services.ConfigureOptions<ConfigureSwaggerOptions>(); // calls .SwaggerExamples()
services.AddSwaggerGenNewtonsoftSupport();
services.AddSwaggerExamples();
services.AddSwaggerExamplesFromAssemblyOf<AddressExample>();

AddressController.cs minus other endpoints

[ApiVersion("1.0")]
[ApiController]
[Route("api/v{api-version:apiVersion}/[controller]")]
public class AddressController : ControllerBase
{
    [HttpPost]
    [Ok(typeof(Address))]
    [BadRequest]
    [SwaggerRequestExample(typeof(Address), typeof(AddressExample))]
    public IActionResult AddAddress([FromBody] Address address)
    {
        return Ok(_service.AddAddress(address)); // The service is just a pass-through layer at the moment
    }
}

AddressExample.cs

public class AddressExample : IExamplesProvider<Address>
{
    public Address GetExamples()
    {
        return new Address
        {
            Id = Guid.NewGuid(),
            BinaryAddress = 246L,
            Distance = 123
        };
    }
}

Based on the above code, I'm only expecting the request example to be set. However, the response example is set too. Even more inexplicable to me is that not only that but any endpoint that uses the Address model in either the request or response has the example set as well.

In my attempt to configure this correctly, I discovered that this line

services.AddSwaggerExamplesFromAssemblyOf<AddressExample>();

Is setting the defined example in all instances of the address model even if I don't use the SwaggerRequestExample attribute annotated on my controller endpoint.

I'm currently at a loss as to how to set the examples with out of the box swagger configuration correctly without creating an example for every instance that the model in question is used.

Can someone point me in the right direction or provide an example that should work? Thanks.

Edit: I will be more than happy to provide additional code as well

0 Answers
Related