Swagger or OpenApi 3.0 examples in Swashbuckle.AspNetCore

If you’d like to generate request and response examples for your APIs, you no longer need to use my Swashbuckle.AspNetCore.Filters package.

Since May 2018, Swashbuckle.AspNetCore supports adding examples via XML comments.

For installation instructions, see the instructions in Swashbuckle.AspNetCore’s readme.

Request examples – POST

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpPost]
    public void Submit(WeatherForecast forecast)
    {
        // blah
    }
}

public class WeatherForecast
{
    /// <summary>
    /// The date of the forecast in ISO-whatever format
    /// </summary>
    public DateTime Date { get; set; }

    /// <summary>
    /// Temperature in celcius
    /// </summary>
    /// <example>25</example>
    public int TemperatureC { get; set; }

    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    /// <summary>
    /// A textual summary
    /// </summary>
    /// <example>Cloudy with a chance of rain</example>
    public string Summary { get; set; }
}

Results in:

Request examples – GET

OpenApi 3.0 supports examples on querystring parameters, which is pretty handy. Just add example= to the param:

/// <summary>
/// Retrieves a specific product by unique id
/// </summary>
/// <param name="id" example="123">The product id</param>
[HttpGet("{id}")]
public Product GetById(int id)

Courtesy of my pull request :-)

Or if you’ve got a reference type in your request (who would do that?), it still works:

// e.g. https://localhost:5001/weatherforecast/AU/MEL/1/2/2020
[HttpGet]
[Route("{country}/{city}/{day}/{month}/{year}")]
public string Get([FromRoute]WeatherRequest wr)
{
    // blah
}

public class WeatherRequest {
    /// <summary>
    /// The 2 digit country code
    /// </summary>
    /// <example>New Zealand, bro</example>
    public string Country { get; set;}
    public string City { get; set; }
    public int Day { get; set; }
    public int Month { get; set; }
    public int Year { get; set; }
}

Response examples

Response examples, again just add XML comments to your response class, and [ProducesResponseType]

[HttpGet]
[ProducesResponseType(typeof(WeatherForecast), StatusCodes.Status200OK)]
public WeatherForecast Get()
{
    // blah
}

// see WeatherForecast at the top of this post

Again, for installation instructions, see the instructions in Swashbuckle.AspNetCore’s readme.

27 thoughts on “Swagger or OpenApi 3.0 examples in Swashbuckle.AspNetCore

  1. So this addition makes it possible to use XML to add one example to a request/response class, right? I have an API where I have many endpoints using the same class, but where I need different examples. Can this way of using XML comments be used to specify the different example values of the request class for the individual endpoint? (From what I read from the Swashbuckle.Examples github, multiple examples for a single request class used to be impossible)

    • If your API accepts the same request for different endpoints, and you want to have different examples for each endpoint, then you’ll need to use my Swashbuckle.AspNetCore.Filters package.

      • (Seems my reply wasn’t submitted successfully, so I will repeat it, apologies if I just can’t see it yet)

        Thanks for your feedback! The project is running is not core, but standard .net framework 4.6 I think. Is there any way I can use those filters anyway?

      • You’re correct with your earlier comment – Swashbuckle.Examples only supports one example for each type on the request. It does support different examples for the same type on the response.

      • Indeed, thanks for the confirmation! I’d like to use your Swashbuckle.AspNetCore.Filters package instead, but I suppose this implies that my project also has to run asp.net core? My project is running framework 4.6, so I’m not sure if they are compatible. I realized this when your installation/use readme referred to files that didn’t exist in my project. Is there a way around this?

      • We’re getting off topic from this blog post, but yes, you’d need to upgrade to ASP.NET Core, which probably isn’t worth it. If however you’re starting a new project, then you should be using .NET Core instead of .NET Framework.

  2. I try to force a ‘date’ format like in your example above
    /// {summary}
    /// The date of the forecast in full-date format
    /// {/summary}
    /// {example}2020-05-31{/example}
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }

    but the example does not appear to use the expected full-date format:
    {
    “name”: “date”,
    “in”: “query”,
    “description”: “The date of the forecast in full-date format”,
    “schema”: {
    “type”: “string”,
    “description”: “The date of the forecast in full-date format”,
    “format”: “date”,
    “nullable”: true,
    “example”: “31/05/2020 12:00:00 AM”
    }
    }

    Is there any way to have the example show in default swagger date format or same way as specified in the example xdoc?

  3. Hey Matt! I am currently having a slight problem with swashbuckle and maybe you could help me. Is there any way I can remove a field only from the example Json and keep it in the schema? Also, appreciate your work a lot man!

  4. Is there any way to specify examples for readonly fields? I am using proto3 which generates all array fields in the C# class as readonly and there does not seem to be a way to override that. I would like our end users to be able to see an example value in “Try it out” for these fields in the swagger doc however readonly fields never show up there.

      • Sure, here is the proto file:

        message DataRequest {
        repeated string ids = 1;
        google.protobuf.StringValue someField = 2;
        google.protobuf.StringValue someOtherField = 3;
        }

        This generates the a C# class with the following fields:

        public sealed partial class DataRequest : pb::IMessage {

        private readonly pbc::RepeatedField ids_ = new pbc::RepeatedField();
        public pbc::RepeatedField Ids { … }

        private string someField_;
        public string SomeField { … }

        private string someOtherField_;
        public string SomeOtherField { … }
        }

        So when Swashbuckle generates the swaggerdoc in the example above, you will see someField and someOtherField in the “Example value” but you won’t see the ids field. The ids field will only show up if you click on the “Schema” tab. This is a little misleading to end users since they can technically submit a value for ids when they use the “Try it out” feature but they wouldn’t be able to tell that is an option from the displayed “Example value”.

      • I guess it’s because pbc::RepeatedField is not a value type (int, string, etc). You should be able to create an example for that using my Swashbuckle.AspNetCore.Filters NuGet package.

  5. We have a controller action with [FromBody]List organizationIds, and Swachbuckle generates a default value (a list with a single guid) which we would like to change. However, adding a param tag with an example attribute doesn’t do the trick and since List is a built in type we can’t add the example there. Do you think we can use a custom type in which we can add the example we want (perhaps by extending List) or can you think of any other way?

  6. Hello,
    Do know how to manage this use case:

    ///
    /// The label of the model
    ///
    /// ???
    public Dictionary Label { get; set; }

    I would like to have in my swagger UI request example:
    {

    “label”: {
    “en”: “my label”,
    “fr”: “mon label”,
    }
    }

    Thanks

  7. I want to use the expamples by xml comments in my controller . I have a post with in the body an object
    I placed the comments but in the request the body on the swagger page is empty.
    So i get noexample there. Can you procide an exampl? Or what is going wrong?
    I use Swashbuckle.AspNetCore” Version=”5.6.3″
    in my controller
    /////
    /////
    /////
    ///// <param name="request"
    /////
    [HttpPost]
    [AuthorizeRoles(UserRoles.GreenhouseTechnician)]
    [ProducesResponseType(typeof(IndoorLocationDto), (int)HttpStatusCode.OK)]
    [ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)]
    [ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)]

    public async Task SetLocationOfItem([FromBody] SetLocationOfItemHandler.Request request)

    and my object
    public class Request : IRequest<HttpResult>
    {
    ///
    /// bc
    public string Barcode { get; }
    ///
    /// typee
    public string Type { get; }
    ///
    /// 1
    public long Id { get; }

    public Request(string barcode, string type, long id)
    {
    Barcode = barcode;
    Type = type;
    Id = id;
    }
    }

    • I provided an example in my blog post, did you read it?

      I can’t really help you as it looks like the blog comment engine has stripped out a lot of what you have posted.

  8. Hey Matt, love this change, much cleaner. Just got a question and wondering if I’m missing something.

    We provide an formatted error response from our APIs, and our controller methods look like so:

    [ProducesResponseType(typeof(Response404), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(Response400), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Response500), StatusCodes.Status500InternalServerError)]
    [ProducesResponseType(typeof(Response422), StatusCodes.Status422UnprocessableEntity)]

    These response objects inherit from ‘Error’ and don’t add anything new, the only reason we create these objects is so that we can have our nice swagger with custom error messages for each response. So rather messily we have an individual example object we then put a custom error message into for each.

    It works and gets the swagger looking nice, but there is a lot of messy code.

    Would be great if there was instead something like

    [ProducesResponseType(typeof(Error), , StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(Error), , StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Error), , StatusCodes.Status500InternalServerError)]
    [ProducesResponseType(typeof(Error), , StatusCodes.Status422UnprocessableEntity)]

    Is there anything that already exists like this? It’s a very petty thing I’m asking, as we can just use the Error object and

    • Hi Owen,
      I tend to use [SwaggerResponse] instead of [ProducesResponseType], because [SwaggerResponse] allows you to pass a description in, e.g.
      [SwaggerResponse(404, type: typeof(ErrorResponse), description: “Could not find the person”)]

      I guess since all of your controllers will have those responses, perhaps you could put the annotations on the controller itself instead of on each method in the controller – that might also reduce the clutter.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s