1

I have an API and associated Swagger docs

I have an ASP.NET Core 7 API project, wired up to produce Swagger documentation. The pertinent initialization code, in Program.cs, looks like this:

// Initialization
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;

// Configure Swagger
// See: https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(options => {
    // Basic API info
    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo {
        Title = "My example API",
        Version = "v1",
        Description = "REST API for interacting with my example functions and data",
        TermsOfService = new Uri("https://example.com/ApiTermsOfUse")
    });

    // Wire up the XML comments, which have been generated in .xml files in more than one project
    foreach (var filePath in System.IO.Directory.GetFiles(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!), "*.xml")) {
        try {
            options.IncludeXmlComments(filePath);
        }

        catch (Exception ex) when(ex.OkToCatch()) {
            // <Ignore the exception>
        }
    }
});

My API contains several controllers (PatientAppController, ProviderController, and ServerInfoController), each of which produces a separate section in the Swagger display.

enter image description here

Now I want to deprecate version 1.0 of the PatientApp part of the API and add version 2.0 of those same API endpoints.

So, I copied PatientAppController to a new PatientAppV2Controller and added some attributes to the class definitions:

PatientAppController

    [ApiController]
    [Route("v{version:apiVersion}/[controller]/[action]")] // Rout: https://example.com/v1/PatientApp/SomeAction
    [ApiVersion("1.0", Deprecated = true)]                 // This is API v1, and it's deprecated
    [Authorize()]
    [Obsolete("Removed in API version 2.0")]               // Tell the compiler it's deprecated
    public partial class PatientAppController : ControllerBase
    { ... }

PatientAppV2Controller

    [ApiController]
    [Route("v{version:apiVersion}/PatientApp/[action]")]   // Rout: https://example.com/v2/PatientApp/SomeAction
    [ApiVersion("2.0")]                                    // This is API v2
    [Authorize()]
    public partial class PatientAppController : ControllerBase
    { ... }

and I added this additional configuration to Program.cs:

was:

// -- Configure the HTTP request pipeline
app.UseSwagger();
app.UseSwaggerUI();

added Swagger endpoints:

// -- Configure the HTTP request pipeline
app.UseSwagger();
app.UseSwaggerUI(options => {
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "Indigo Health API V1");
    options.SwaggerEndpoint("/swagger/v2/swagger.json", "Indigo Health API V2");
});

Now, the Swagger display is weird

The "version 1" page looks correct:

After: V1 page

but the "version 2" page (select "Indigo Health API V2 from the drop-down at the top of the page) displays a mangled version of the controller name (PatientAppV - no clue why it isn't PatientAppV2):

enter image description here

At last... the question

How do I change the name Swagger displays for the "section"

I want Swagger to display the section name associated with my PatientAppV2Controller as PatientApp on the page shown above, not PatientAppV. How do I do this?

Bob.at.Indigo.Health
  • 11,023
  • 13
  • 64
  • 111
  • 1
    To be honest, I can't reproduce your issue because both V1 or V2 in my side, they both don't have a `V` in controller, so I want to double confirm that, do your 2 controllers have the same controller name `PatientAppController`? if not, does it mean you have a controller `PatientAppController` and another is `PatientAppV2Controller`? then [this answer](https://stackoverflow.com/a/73337378) may help understand. – Tiny Wang Mar 17 '23 at 08:43
  • https://i.stack.imgur.com/mkd8y.png and https://i.stack.imgur.com/dYgLF.png – Tiny Wang Mar 17 '23 at 08:44
  • I have `PatientAppController` and `PatientAppV2Controller`. The answer you point to looks to be spot-on for my issue. Honestly, I haven't read that answer carefully yet, but I'm guessing the solution to my problem is something like naming my two controllers `PatientApp1Controller` and `PatientApp2Controller`, and adjusting the routing attributes. – Bob.at.Indigo.Health Mar 17 '23 at 19:51
  • thank you very much for your kind reply and my idea is the same with yours... And in my test, my Controllers had the same name but V1 and V2 are in different folder so that I can keep 2 controllers existed at the same time. – Tiny Wang Mar 18 '23 at 14:19

1 Answers1

0

Thanks to Tiny Wang, who pointed me at this SO answer!

Apparently, the Swagger document generator makes assumptions about the "group" labels ("PatientApp", "Provider", etc.) based on the names of the controller classes. If you want to have different "versions" of the same controller, the controller classes should be named {Group}n{Controller}, where {Group} is the text that appears in the Swagger UI.

In my case, I renamed the two affected controller classes PatientApp1Controller and PatientApp2Controller. Now, the Swagger UI displays a PatientApp "group" in both versions of the document.

BTW, I would be forever grateful if someone reading this could post a comment or edit this answer to point to the documentation that describes this behavior!

Bob.at.Indigo.Health
  • 11,023
  • 13
  • 64
  • 111