what is the purpose of {documentname} in the RouteTemplate config?

Viewed 794

https://github.com/domaindrivendev/Swashbuckle.AspNetCore

By default, Swagger JSON will be exposed at the following route - "/swagger/{documentName}/swagger.json". If necessary, you can change this when enabling the Swagger middleware. Custom routes MUST include the {documentName} parameter.

Why does the template config require this placeholder but the UI config does not?

app.UseSwagger(c =>
{
    c.RouteTemplate = "api-docs/{documentName}/swagger.json";
})
NOTE: If you're using the SwaggerUI middleware, you'll also need to update its configuration to reflect the new endpoints:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My API V1");
})

What is {documentName} for? Is there a feature to swap it out dynamically or something? Because the UI config in the example has it statically configured. why wouldn't it just be "/api-docs/v1/swagger.json" in the RouteTemplate config too?

1 Answers

documentName

The {documentName} refers to the name you specify in the AddSwaggerGen() method.

The following code uses myapi as the name for a swagger document.

builder.Services.AddSwaggerGen(options =>
  options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" })
);

Using UseSwagger as follows

app.UseSwagger(options =>
  options.RouteTemplate = "swagger/{documentName}/swagger.json");

leads to a swagger file being created the following location: /swagger/myapi/swagger.json

Which means your Swagger UI configuration must be

app.UseSwaggerUI(options => {
  options.SwaggerEndpoint("/swagger/myapi/swagger.json", "Swagger v1");
});

The Swagger UI can make a UI based on any swagger file, whether it comes from this project or not. That's why it doesn't include the {documentName} placeholder. There isn't a relationship between these, necessarily.

Multiple Swagger UIs

This, for example, is the configuration where I have 1 Swagger Doc, 2 swagger files, and two UI endpoints. I describe the same API, but once using the OpenAPI v3 standard, and once using the old Swagger v2 standard.

builder.Services.AddSwaggerGen(options =>
{
  options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" });
});

app.UseSwagger(options =>
{
  options.SerializeAsV2 = true;
  options.RouteTemplate = "swagger/{documentName}/swaggerV2.json";
});

app.UseSwagger(options =>
{
  options.SerializeAsV2 = false;
  options.RouteTemplate = "swagger/{documentName}/openapiV3.json";
});

app.UseSwaggerUI(options => {
  options.SwaggerEndpoint("/swagger/myapi/openapiV3.json", "OpenApi v3");
  options.SwaggerEndpoint("/swagger/myapi/swaggerV2.json", "Swagger v2");
});

When you go to the swagger UI, you will see a dropdown to select one of the two endpoints.

Multiple Swagger Docs

Your app can also have multiple swagger docs. E.g. your 'normal' API + some legacy API stuff.

options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" });
  options.SwaggerDoc("myapiLegacy", new OpenApiInfo { Title = "My Legacy API", Version = "v1" });

There are several ways to specify when a method of your project belongs to a certain swagger doc. But the easiest way is to mark it with an attribute:

[HttpPost]
[ApiExplorerSettings(GroupName = "myapiLegacy")]
public void Post([Product product)

So since you can have multiple swagger docs, it makes sense to create a placeholder for it. i.e., {documentName}.

In my swagger UI I now end up with 4 endpoints:

  • normal api as Swagger V2
  • normal api as OpenApi V3
  • legacy api as Swagger V2
  • legacy api as OpenApi V3
Related