Hi I create an API in C# and use SwaggerUI to test my api.
I woud know if it's possible to automatly collaps all endpoint groups in the interface
SwaggerUI Picture
here is my code to generate my interface
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
AddCORS(builder);
AddDatabase(builder);
AddServices(builder);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
var API_NAME = Assembly.GetExecutingAssembly().GetName().Name;
var xmlPath = $"{AppContext.BaseDirectory}{API_NAME}.xml";
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = API_NAME,
Description = "API for Guanajuato RolePlay"
});
c.IncludeXmlComments(xmlPath);
});
var app = builder.Build();
Add this code.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(o =>
{
o.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);
});
}
it will give you result like this.
Related
I have an ASPNET Core 6 service which uses Duende IdentityServer 6, which includes several endpoints such as /connect/token and /connect/authorize. I need these endpoints to show up in my Swagger UI page, however I cannot find a way to get them to show up.
Here is my AddSwaggerGen
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
ClientCredentials = new OpenApiOAuthFlow
{
AuthorizationUrl =
new Uri($"{builder.Configuration.GetSection("BaseUri").Value}connect/authorize",
UriKind.RelativeOrAbsolute),
TokenUrl = new Uri($"{builder.Configuration.GetSection("BaseUri").Value}connect/token",
UriKind.RelativeOrAbsolute),
Scopes = new Dictionary<string, string>
{
{ Constants.Api.ScopeName, "Base level access to API" }
}
}
}
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" },
In = ParameterLocation.Cookie
},
new string[] { }
}
});
});
And I am just using the basic app.AddSwagger() and app.AddSwaggerUI()
As far as my research has shown, CodingMytra is correct. IdentityServer endpoints must be added manually to the Swagger document.
I am trying to get the hang of swagger in minimal API. I have the following code:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(setup => setup.SwaggerDoc("v1", new OpenApiInfo()
{
Description = "An api that will change your life for ever",
Title = "Alert Api",
Version = "v1",
Contact = new OpenApiContact()
{
Name = "Grundfos",
Url = new Uri("https://grundfos.com")
}
}));
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//Map endpoints
app.MapGet("/alerts", async () => Results.Ok());
app.MapGet("/profiles", async () => Results.Ok());
this gives a swagger UI looking like this:
My question is: How do you sort the endpoints to be under a headline called "alerts" and "profiles"?
I think what you are after is something called Tags in swagger.
You can add WithTags at the end of your mapping, like so:
//Map endpoints
app.MapGet("/alerts", async () => Results.Ok()).WithTags("Alerts");
app.MapGet("/profiles", async () => Results.Ok()).WithTags("Profiles");
The result looks like this:
Alternatively you can also take another approach by configuring the AddSwaggerGen method.
In there you can take the first segment of the URL endpoint and use that as the tag name.
For example, the endpoints alerts and alerts/delete will both be placed in a section called alerts.
builder.Services.AddSwaggerGen(c =>
{
c.TagActionsBy(d =>
{
var rootSegment = d.RelativePath?
.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault() ?? "Home";
return new List<string> { rootSegment! };
});
})
//Map endpoints without 'WithTags`
app.MapGet("/alerts", async () => Results.Ok());
app.MapGet("/alerts/delete", async () => Results.Ok());
app.MapGet("/profiles", async () => Results.Ok());
If you have a bunch of related endpoints and you want to group them in one tag SomethingEndpoints, you can do it by creating a static class named SomethingEndpoints and defining an extension method MapSomethingEndpoints() as follows.
Notes:
The automatically added tags are only available when passing method Job.
Passing (int y) => Job(y) or (int z) => z does not. You need to attach WithTags() manually in this case.
I don't know whether it is a feature by design or a bug!
SomethingEndpoints.cs
static class SomethingEndpoints
{
public static void MapSomethingEndpoints(this IEndpointRouteBuilder routes)
{
var group = routes.MapGroup("/api/v1/job");
group.MapGet("/{x:int}", Job);// no need WithTags!
group.MapGet("/{y:int}", (int y) => Job(y)).WithTags(nameof(SomethingEndpoints));
group.MapGet("/{z:int}", (int z) => z).WithTags(nameof(SomethingEndpoints));
}
static int Job(int x) => x;
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapSomethingEndpoints();
app.Run();
As the title suggests, i have a .net 6 web api that I'm trying to add versioning to but swagger (swashbuckle) does not seem to understand whats going on.
Program.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning(setup =>
{
setup.DefaultApiVersion = new ApiVersion(1, 0);
setup.AssumeDefaultVersionWhenUnspecified = true;
setup.ReportApiVersions = true;
});
ConfigureServices(builder.Services);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"v1");
c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"v2");
});
app.Run();
void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore();
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = false;
options.ApiVersionReader = new UrlSegmentApiVersionReader();
});
services.AddSwaggerGen();
}
I have annotated my controllers like so:
[ApiVersion("1.0")]
[Route("api/v1/[controller]")]
[ApiController]
public class MessageController : ControllerBase
[ApiVersion("2.0")]
[Route("api/v2/[controller]")]
[ApiController]
public class MessageController : ControllerBase
The swagger document that is generated looks like this:
And if i select v2 from the drop down, I get this:
Nuget packages and versions installed are:
Can anyone tell me where I'm going wrong.
You'll need to add the swagger documents themselves, not just the UI for them. In your AddSwaggerGen method, add something like:
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "My API" });
c.SwaggerDoc("v2", new OpenApiInfo { Version = "v2", Title = "My API" });
});
This article seems to have covered all the aspect what you are looking for.
Please have a look.
https://referbruv.com/blog/integrating-aspnet-core-api-versions-with-swagger-ui/
Besides passing the configuration here:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API - V1", Version = "v1" });
c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API - V2", Version = "v2" });
});
According to the docs you have to specify the GroupName of the controller:
[ApiVersion("2.0")]
[Route("api/v2/[controller]")]
[ApiController]
[ApiExplorerSettings(GroupName = "v2")]
public class MessageController : ControllerBase
Also, the docs show ways to customize and add conventions.
I just upgraded my project from Swashbuckle 5.6.3 to 6.0.7. I have made no code changes, but now when attempting to use the Swagger page to test the API, the URL generated by Swagger is not using https even though the page is loaded through https and all the documentation I can find says that it should infer the scheme based on the URL used to load the Swagger page.
Here is the configuration code:
services.AddSwaggerGen(c => {
c.SwaggerDoc(apiSettings.Version, new OpenApiInfo { Title = apiSettings.Name, Version = apiSettings.Version });
c.CustomSchemaIds(type => type.FullName);
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "bearer",
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{ new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new List<string>() }
});
});
and:
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint($"/swagger/{apiSettings.Version}/swagger.json", $"{apiSettings.Name} {apiSettings.Version}");
});
Is there a new configuration setting to specify the scheme now?
In version 6.0.7, you can change this behavior with the MapSwagger extension method.
app.UseEndpoints(endpoints =>
{
...
endpoints.MapSwagger($"/swagger/{apiSettings.Version}/swagger.json", o =>
{
o.PreSerializeFilters.Add((swagger, httpReq) =>
{
swagger.Servers.Clear();
});
});
});
In the end, this is the final code that worked for me.
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapSwagger("/swagger/{documentName}/swagger.json", options => {
options.PreSerializeFilters.Add((swagger, httpRequest) => { });
});
});
I have basic Api that accepts a default header value for my-api-key and the corresponding value.
I'm trying to get the Swagger UI to allow me to enter the header one time for Authorization and have the key/value passed along with every request.
So far, I've only been successful with explicitly adding the header as a parameter to every endpoint, but that isn't ideal.
Relevant code snippets:
services.AddApiVersioning(
options =>
{
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
});
services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" });
c.SwaggerDoc("v2", new OpenApiInfo { Title = "Api", Version = "v2" });
// this isn't ideal as I have to fill in the Api Key on ever request
//c.OperationFilter<ApiKeySwaggerFilter>();
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.ApiKey,
Name = "my-api-key",
In = ParameterLocation.Header
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ new OpenApiSecurityScheme()
{
// Type = SecuritySchemeType.ApiKey,
Name = ""
//In = ParameterLocation.Header
//Reference = new OpenApiReference()
//{
// Id = "myToken",
// Type = ReferenceType.SecurityScheme
//},
}, new string[] { }
}
});
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Api v1");
c.SwaggerEndpoint("/swagger/v2/swagger.json", "Api v2");
});
Corresponding image of where I'm at:
Corresponding minimal spike: https://github.com/aherrick/SwaggerSample
I feel this is close, but how do I get the Api Header to get passed on every request, without having to force the user to fill in parameter on every method request.
Figured it out with the following section update:
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
{
Description = "Enter your Api Key below:",
Name = "my-api-key",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "ApiKey"
},
},
new List<string>()
}
});