TheDoomDestroyer
TheDoomDestroyer

Reputation: 2995

Swagger response description not shown

I am currently attempting to display a description of a particular response in Swagger UI, but there doesn't seem to be a documentation that truly covers all aspects of that, and all the examples I've tried from Get started with Swashbuckle and ASP.NET Core don't work in .NET Core 3.1...

        /// <summary>
        /// Test route...
        /// </summary>
        /// <returns></returns>
        /// <response code="200">This is a test</response>
        [HttpGet]
        [ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
        public IActionResult Get()
        {
            return Ok("Hello World");
        }

My .csproj contains the following as well:

  <PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <NoWarn>$(NoWarn);1591</NoWarn>
  </PropertyGroup>

The Swagger UI ends up looking like this (and as you can see, the "Descriptipn" column doesn't contain the "This is a test" text as it probably should). Am I missing something?

Image preview

I also had added [SwaggerResponse(StatusCodes.Status200OK, ...)] to it, but nothing changes.

Upvotes: 15

Views: 20326

Answers (3)

Alex Klaus
Alex Klaus

Reputation: 8934

Since .NET v6 there're two ways of managing the API: classic API controllers and minimal API. They're quite different, so I provide two answers below.

For the classic/traditional API controllers

As per the official docs, it's done via XML comment with a combination of ProducesResponseType attribute:

<response code="201">This is a test</response>
[ProducesResponseType(StatusCodes.Status201Created)]

The comments need to be linked to Swagger

builder.Services.AddSwaggerGen(options =>
{
    // using System.Reflection;
    var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});

For the minimal API

In .NET 6, the minimal API is quite raw, with patchy support from both NSwag and Swashbuckle. It only supports the old-school attributes (as per this post on SO):

app.MapGet("/clients",
    [SwaggerOperation(
        Summary = "returns clients",
        Description = "more description on get `clients`")]
    [SwaggerResponse(200, "success")]
    [SwaggerResponse(500, "some failure")]
    async (IClientRepository repo) =>
    {
        var results = await repo.GetClientsAsync();
        return mapper.Map<IEnumerable<ClientModel>>(results);
    }).WithTags("Clients");

.NET 7 has several useful extension methods added. One of them is Produces that provides the type and HTTP code but lacks a handy message:

app.MapGet("/clients",
    async (IClientRepository repo) =>
    {
        var results = await repo.GetClientsAsync();
        return mapper.Map<IEnumerable<ClientModel>>(results);
    }).Produces<IEnumerable<ClientModel>>(StatusCodes.Status200OK)
      .WithTags("Clients")
      .WithSummary("returns clients")
      .WithDescription("more description on get `clients`");

The advantage of using those extension methods is that you can apply them in bulk, for example:

var routes = new[] { 
    app.MapGet("/clients", (IClientRepository repo) => repo.GetClients()),
    app.MapGet("/users", (IUserRepository repo) => repo.GetUsers()),
};
foreach (var route in routes)                               
    route.WithTags("Lists");    

Upvotes: 10

TheDoomDestroyer
TheDoomDestroyer

Reputation: 2995

As it turns out, [SwaggerResponse] works properly, but before, I need to "enable annotations" in my Startup...

    services.AddSwaggerGen(config =>
    {
        config.SwaggerDoc("v1", new OpenApiInfo
        {
            Title = "Some API",
            Version = "v1"
        });

        config.EnableAnnotations();
    });

Upvotes: 24

NotFound
NotFound

Reputation: 6102

In your project properties you should check Output XML documentation file found under the blade Build. Then in your startup file:

services.AddSwaggerGen(c =>
{
    //rest of your code

    //i'm using the default path generated, but you can adjust it as you want
    var XMLPath = AppDomain.CurrentDomain.BaseDirectory + nameof(MyNamespace) + ".xml";
    if (File.Exists(XMLPath))
    {
        c.IncludeXmlComments(XMLPath);
    }
});

If that still doesn't work check if the xml file appears in the bin folder. If not check the properties within Visual Studio and adjust Copy to output directory to Copy or Copy if newer.

Upvotes: 2

Related Questions