« Swashbuckle » : différence entre les versions
Apparence
(47 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 3 : | Ligne 3 : | ||
* [https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1 ASP.NET Core Web API help pages with Swagger / Open API] | * [https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1 ASP.NET Core Web API help pages with Swagger / Open API] | ||
* [https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-2.1&tabs=visual-studio-code%2Cvisual-studio-xml Get started with NSwag and ASP.NET Core] | * [https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-2.1&tabs=visual-studio-code%2Cvisual-studio-xml Get started with NSwag and ASP.NET Core] | ||
* [https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-5.0&tabs=visual-studio-code Swashbuckle] | |||
= | = Installation = | ||
<kode lang=' | {{warn | It is no longer actively maintained and has been remove from .NET 9 templates. [https://github.com/dotnet/aspnetcore/issues/54599 ]}} | ||
<kode lang='ps'> | |||
dotnet add | dotnet add package Swashbuckle.AspNetCore | ||
</kode> | |||
<filebox fn='Program.cs'> | |||
builder.Services.AddEndpointsApiExplorer(); | |||
builder.Services.AddSwaggerGen(); | |||
if (app.Environment.IsDevelopment()) | |||
{ | |||
app.UseSwagger() | |||
.UseSwaggerUI(); | |||
} | |||
</filebox> | |||
= Installation Old = | |||
<kode lang='bash'> | |||
dotnet add package Swashbuckle.AspNetCore | |||
</kode> | </kode> | ||
<filebox fn='Startup.cs'> | <filebox fn='Startup.cs'> | ||
public void ConfigureServices(IServiceCollection services) | public void ConfigureServices(IServiceCollection services) | ||
{ | { | ||
services. | services.AddControllers(); | ||
services.AddSwaggerGen(c => | |||
{ | |||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "EFWebApi", Version = "v1" }); | |||
}); | |||
} | |||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | { | ||
app. | if (env.IsDevelopment()) | ||
{ | |||
app.UseDeveloperExceptionPage(); | |||
app.UseSwagger(); | |||
app.UseSwaggerUI(c => | |||
{ | |||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "EFWebApi v1"); | |||
c.RoutePrefix = string.Empty; // serve the Swagger UI at the app's root (http://localhost:<port>/) | |||
}); | |||
} | |||
</filebox> | |||
= Usage = | |||
<filebox fn='Controllers/ItemController.cs'> | |||
[ApiController] | |||
[Route("[controller]")] | |||
[Produces("application/json")] // set the Media type | |||
public class ItemController : ControllerBase | |||
{ | |||
[HttpGet] | |||
[ProducesResponseType(typeof(IEnumerable<Item>), StatusCodes.Status200OK)] // set the status code and the return type | |||
public IActionResult Get() { /* ... */ } | |||
} | |||
</filebox> | |||
= [https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-7.0&tabs=visual-studio-code#xml-comments XML documentation] = | |||
{{warn | {{boxx|&}} has to be escaped as {{boxx|&amp;}}}} | |||
<filebox fn='MyProject.csproj' lang='xml'> | |||
<PropertyGroup> | |||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | |||
</PropertyGroup> | |||
</filebox> | </filebox> | ||
<filebox fn='Program.cs'> | |||
<filebox fn=' | builder.Services.AddSwaggerGen( | ||
options => | |||
{ | |||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My Web Api", Version = "v1" }); | |||
public | // Set the comments path for the Swagger JSON and UI. | ||
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; | |||
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); | |||
}); | |||
} | |||
</filebox> | |||
<filebox fn='Controllers/ItemController.cs'> | |||
[Produces("application/json")] | |||
public class MyController() : ControllerBase | |||
{ | { | ||
/// <summary>Get all the items.</summary> | |||
/// <remarks> | |||
/// Sample request: | |||
/// | |||
/// GET /item | |||
/// </remarks> | |||
/// <response code="200">Returns all the items.</response> | |||
[HttpGet] | |||
public IEnumerable<Item> GetAll() { /* ... */ } | |||
// | /// <summary>Update an item.</summary> | ||
app. | /// <param name="timeSeries">The new time series to add.</param> | ||
/// <remarks> | |||
/// Sample request: | |||
/// | |||
/// PUT /item/9 | |||
/// </remarks> | |||
[HttpPut("{id}")] | |||
[ProducesResponseType(StatusCodes.Status204NoContent)] // by default returning void or Task is associated to status code 200 | |||
public Task UpdateAsync(int id, CreateUpdateItemQuery query) { /* ... */ } | |||
</filebox> | |||
= [https://medium.com/@celery_liu/asp-net-core-web-api-with-swagger-api-versioning-for-dotnet-8-c8ce2fd7808c Version] = | |||
* [[Asp.net_core_8_web_api#Version|ASP.NET Core Version]] | |||
<filebox fn='Program.cs'> | |||
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); | |||
// nuget package Asp.Versioning.Mvc.ApiExplorer | |||
builder.Services | |||
.AddApiVersioning(/* ... */) | |||
.AddApiExplorer( | |||
options => | |||
{ | |||
options.GroupNameFormat = "'v'VVV"; | |||
options.SubstituteApiVersionInUrl = true; | |||
}); | |||
app.UseSwagger(); | |||
app.UseSwaggerUI( | |||
options => | |||
{ | |||
var descriptions = app.DescribeApiVersions(); | |||
foreach (var description in descriptions) | |||
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); | |||
}); | |||
</filebox> | |||
<filebox fn='ConfigureSwaggerOptions.cs'> | |||
public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions> | |||
{ | |||
public void Configure(SwaggerGenOptions options) | |||
{ | { | ||
foreach (var description in provider.ApiVersionDescriptions) | |||
{ | { | ||
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); | |||
} | |||
static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) | |||
=> new() | |||
{ | { | ||
Title = "Power Analytics Model Management API", | |||
Version = description.ApiVersion.ToString(), | |||
Description = "API Description." | |||
}; | }; | ||
} | |||
} | |||
</filebox> | |||
= Document Filter = | |||
<filebox fn='Program.cs'> | |||
builder.Services.AddSwaggerGen(c => | |||
{ | |||
c.DocumentFilter<MyDocumentFilter>(); | |||
}); | |||
</filebox> | |||
<filebox fn='MyDocumentFilter.cs'> | |||
public class MyDocumentFilter : IDocumentFilter | |||
{ | |||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) | |||
{ | |||
// add new property | |||
swaggerDoc.Extensions.Add("propertyName", new OpenApiObject | |||
{ | |||
["propertyName"] = new OpenApiString("value"), | |||
["propertyName"] = new OpenApiArray | |||
{ | { | ||
{ new OpenApiString("value") } | |||
} | |||
} | } | ||
} | |||
} | |||
</filebox> | |||
== [https://vrcode.medium.com/implement-health-check-in-dot-net-core-api-and-integrate-in-swagger-5b812601cb35 Add HealthChecks endpoint] == | |||
<filebox fn='Program.cs' collapsed> | |||
builder.Services.AddHealthChecks(); | |||
builder.Services.AddSwaggerGen(c => | |||
{ | |||
c.DocumentFilter<HealthChecksDocumentFilter>(); | |||
}); | |||
var app = builder.Build(); | |||
app.MapHealthChecks("/health"); | |||
</filebox> | |||
<filebox fn='HealthChecksDocumentFilter.cs' collapsed> | |||
public class HealthChecksDocumentFilter : IDocumentFilter | |||
{ | |||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) | |||
{ | |||
var pathItem = new OpenApiPathItem(); | |||
var operation = new OpenApiOperation(); | |||
operation.Tags.Add(new OpenApiTag { Name = "ApiHealth" }); | |||
var properties = new Dictionary<string, OpenApiSchema> | |||
{ | |||
{ "status", new OpenApiSchema() { Type = "string" } }, | |||
{ "errors", new OpenApiSchema() { Type = "array" } } | |||
}; | }; | ||
}); | |||
var response = new OpenApiResponse(); | |||
response.Content.Add("application/json", new OpenApiMediaType | |||
{ | |||
Schema = new OpenApiSchema | |||
{ | |||
Type = "object", | |||
AdditionalPropertiesAllowed = true, | |||
Properties = properties | |||
} | |||
}); | |||
operation.Responses.Add("200", response); | |||
pathItem.AddOperation(OperationType.Get, operation); | |||
swaggerDoc.Paths.Add("/health", pathItem); | |||
} | |||
} | |||
</filebox> | |||
= [https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-5.0&tabs=visual-studio-code#customize-the-ui Dark theme] = | |||
<filebox fn='Startup.cs'> | |||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | |||
{ | |||
if (env.IsDevelopment()) | |||
{ | |||
app.UseDeveloperExceptionPage(); | |||
app.UseStaticFiles(); | |||
app.UseSwagger(); | |||
app.UseSwaggerUI(c => | |||
{ | |||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "EFWebApi v1"); | |||
c.RoutePrefix = string.Empty; | |||
c.InjectStylesheet("/swagger-ui/dark-theme.css"); | |||
}); | |||
} | |||
</filebox> | |||
<filebox fn='wwwroot/swagger-ui/dark-theme.css' collapsed> | |||
.swagger-ui .topbar .download-url-wrapper .select-label select { | |||
border: 2px solid #89bf04;; | |||
} | |||
body { | |||
background-color: #303030; | |||
} | |||
.swagger-ui, | |||
.swagger-ui .info .title, | |||
.swagger-ui .opblock-tag, | |||
.swagger-ui section.models h4, | |||
.swagger-ui .opblock .opblock-summary-operation-id, | |||
.swagger-ui .opblock .opblock-summary-path, | |||
.swagger-ui .opblock .opblock-summary-path__deprecated, | |||
.swagger-ui table thead tr td, | |||
.swagger-ui table thead tr th, | |||
.swagger-ui .parameter__name, | |||
.swagger-ui .parameter__type, | |||
.swagger-ui .response-col_status, | |||
.swagger-ui .model-title, | |||
.swagger-ui .model, | |||
.swagger-ui .tab li { | |||
color: #f0f0f0; | |||
} | |||
.swagger-ui input[type="email"], | |||
.swagger-ui input[type="file"], | |||
.swagger-ui input[type="password"], | |||
.swagger-ui input[type="search"], | |||
.swagger-ui input[type="text"], | |||
.swagger-ui textarea { | |||
background: #303030; | |||
color: #f0f0f0; | |||
border: 1px solid gray; | |||
} | |||
.swagger-ui .opblock .opblock-section-header { | |||
background-color: #1b1b1b; | |||
} | |||
.swagger-ui .opblock .opblock-section-header h4, | |||
.swagger-ui .btn { | |||
color: #f0f0f0; | |||
} | |||
.swagger-ui input[disabled], .swagger-ui select[disabled], .swagger-ui textarea[disabled] { | |||
background-color: #303030; | |||
color: lightgray; | |||
} | |||
.swagger-ui select { | |||
background: #303030 url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="gray"><path d="M13.418 7.859a.695.695 0 01.978 0 .68.68 0 010 .969l-3.908 3.83a.697.697 0 01-.979 0l-3.908-3.83a.68.68 0 010-.969.695.695 0 01.978 0L10 11l3.418-3.141z"/></svg>') right 10px center no-repeat; | |||
color: #f0f0f0; | |||
} | |||
.swagger-ui .response-control-media-type--accept-controller select { | |||
border-color: #89bf04; | |||
} | |||
.swagger-ui .response-control-media-type__accept-message { | |||
color: #89bf04; | |||
} | |||
.arrow path { | |||
fill: gray; | |||
} | |||
.swagger-ui section.models .model-container { | |||
border: 1px solid #61affe; | |||
} | |||
.swagger-ui .model-toggle::after { | |||
background: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="gray"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>') 50% no-repeat; | |||
} | |||
.swagger-ui .download-contents { | |||
width: unset; | |||
} | |||
</filebox> | </filebox> | ||
= | = [https://stackoverflow.com/questions/61881770/invalidoperationexception-cant-use-schemaid-the-same-schemaid-is-already-us The same schemaId is already used] = | ||
Occurs when you have 2 classes with the same name in different namespaces.<br> | |||
< | Fix it by using the full class name (with namspace) for the schema id. | ||
<filebox fn='Program.cs'> | |||
builder.Services.AddSwaggerGen(options => | |||
{ | |||
options.CustomSchemaIds(type => type.ToString()); | |||
}); | |||
</filebox> | |||
</ | |||
= | = Url = | ||
{| class="wikitable wtp wtmono1" | |||
! Url | |||
! Resource | |||
|- | |||
| <nowiki>http://localhost:<port>/swagger</nowiki> || swagger UI | |||
|- | |||
| <nowiki>http://localhost:<port>/swagger/v1/swagger.json</nowiki> || swagger json | |||
|} | |||
= [https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#starting-a-web-browser Ouvrir le navigateur sur swagger] = | = [https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#starting-a-web-browser Ouvrir le navigateur sur swagger] = |
Dernière version du 18 janvier 2025 à 10:52
Liens
- ASP.NET Core Web API help pages with Swagger / Open API
- Get started with NSwag and ASP.NET Core
- Swashbuckle
Installation
![]() |
It is no longer actively maintained and has been remove from .NET 9 templates. [1] |
dotnet add package Swashbuckle.AspNetCore |
Program.cs |
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
if (app.Environment.IsDevelopment())
{
app.UseSwagger()
.UseSwaggerUI();
}
|
Installation Old
dotnet add package Swashbuckle.AspNetCore |
Startup.cs |
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "EFWebApi", Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "EFWebApi v1");
c.RoutePrefix = string.Empty; // serve the Swagger UI at the app's root (http://localhost:<port>/)
});
}
|
Usage
Controllers/ItemController.cs |
[ApiController]
[Route("[controller]")]
[Produces("application/json")] // set the Media type
public class ItemController : ControllerBase
{
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<Item>), StatusCodes.Status200OK)] // set the status code and the return type
public IActionResult Get() { /* ... */ }
}
|
XML documentation
![]() |
& has to be escaped as & |
MyProject.csproj |
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
|
Program.cs |
builder.Services.AddSwaggerGen(
options =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My Web Api", Version = "v1" });
// Set the comments path for the Swagger JSON and UI.
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});
}
|
Controllers/ItemController.cs |
[Produces("application/json")]
public class MyController() : ControllerBase
{
/// <summary>Get all the items.</summary>
/// <remarks>
/// Sample request:
///
/// GET /item
/// </remarks>
/// <response code="200">Returns all the items.</response>
[HttpGet]
public IEnumerable<Item> GetAll() { /* ... */ }
/// <summary>Update an item.</summary>
/// <param name="timeSeries">The new time series to add.</param>
/// <remarks>
/// Sample request:
///
/// PUT /item/9
/// </remarks>
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] // by default returning void or Task is associated to status code 200
public Task UpdateAsync(int id, CreateUpdateItemQuery query) { /* ... */ }
|
Version
Program.cs |
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
// nuget package Asp.Versioning.Mvc.ApiExplorer
builder.Services
.AddApiVersioning(/* ... */)
.AddApiExplorer(
options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
app.UseSwagger();
app.UseSwaggerUI(
options =>
{
var descriptions = app.DescribeApiVersions();
foreach (var description in descriptions)
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
});
|
ConfigureSwaggerOptions.cs |
public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions>
{
public void Configure(SwaggerGenOptions options)
{
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
}
static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
=> new()
{
Title = "Power Analytics Model Management API",
Version = description.ApiVersion.ToString(),
Description = "API Description."
};
}
}
|
Document Filter
Program.cs |
builder.Services.AddSwaggerGen(c =>
{
c.DocumentFilter<MyDocumentFilter>();
});
|
MyDocumentFilter.cs |
public class MyDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
// add new property
swaggerDoc.Extensions.Add("propertyName", new OpenApiObject
{
["propertyName"] = new OpenApiString("value"),
["propertyName"] = new OpenApiArray
{
{ new OpenApiString("value") }
}
}
}
}
|
Add HealthChecks endpoint
Program.cs |
builder.Services.AddHealthChecks();
builder.Services.AddSwaggerGen(c =>
{
c.DocumentFilter<HealthChecksDocumentFilter>();
});
var app = builder.Build();
app.MapHealthChecks("/health");
|
HealthChecksDocumentFilter.cs |
public class HealthChecksDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var pathItem = new OpenApiPathItem();
var operation = new OpenApiOperation();
operation.Tags.Add(new OpenApiTag { Name = "ApiHealth" });
var properties = new Dictionary<string, OpenApiSchema>
{
{ "status", new OpenApiSchema() { Type = "string" } },
{ "errors", new OpenApiSchema() { Type = "array" } }
};
var response = new OpenApiResponse();
response.Content.Add("application/json", new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
AdditionalPropertiesAllowed = true,
Properties = properties
}
});
operation.Responses.Add("200", response);
pathItem.AddOperation(OperationType.Get, operation);
swaggerDoc.Paths.Add("/health", pathItem);
}
}
|
Dark theme
Startup.cs |
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "EFWebApi v1");
c.RoutePrefix = string.Empty;
c.InjectStylesheet("/swagger-ui/dark-theme.css");
});
}
|
wwwroot/swagger-ui/dark-theme.css |
.swagger-ui .topbar .download-url-wrapper .select-label select {
border: 2px solid #89bf04;;
}
body {
background-color: #303030;
}
.swagger-ui,
.swagger-ui .info .title,
.swagger-ui .opblock-tag,
.swagger-ui section.models h4,
.swagger-ui .opblock .opblock-summary-operation-id,
.swagger-ui .opblock .opblock-summary-path,
.swagger-ui .opblock .opblock-summary-path__deprecated,
.swagger-ui table thead tr td,
.swagger-ui table thead tr th,
.swagger-ui .parameter__name,
.swagger-ui .parameter__type,
.swagger-ui .response-col_status,
.swagger-ui .model-title,
.swagger-ui .model,
.swagger-ui .tab li {
color: #f0f0f0;
}
.swagger-ui input[type="email"],
.swagger-ui input[type="file"],
.swagger-ui input[type="password"],
.swagger-ui input[type="search"],
.swagger-ui input[type="text"],
.swagger-ui textarea {
background: #303030;
color: #f0f0f0;
border: 1px solid gray;
}
.swagger-ui .opblock .opblock-section-header {
background-color: #1b1b1b;
}
.swagger-ui .opblock .opblock-section-header h4,
.swagger-ui .btn {
color: #f0f0f0;
}
.swagger-ui input[disabled], .swagger-ui select[disabled], .swagger-ui textarea[disabled] {
background-color: #303030;
color: lightgray;
}
.swagger-ui select {
background: #303030 url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="gray"><path d="M13.418 7.859a.695.695 0 01.978 0 .68.68 0 010 .969l-3.908 3.83a.697.697 0 01-.979 0l-3.908-3.83a.68.68 0 010-.969.695.695 0 01.978 0L10 11l3.418-3.141z"/></svg>') right 10px center no-repeat;
color: #f0f0f0;
}
.swagger-ui .response-control-media-type--accept-controller select {
border-color: #89bf04;
}
.swagger-ui .response-control-media-type__accept-message {
color: #89bf04;
}
.arrow path {
fill: gray;
}
.swagger-ui section.models .model-container {
border: 1px solid #61affe;
}
.swagger-ui .model-toggle::after {
background: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="gray"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>') 50% no-repeat;
}
.swagger-ui .download-contents {
width: unset;
}
|
The same schemaId is already used
Occurs when you have 2 classes with the same name in different namespaces.
Fix it by using the full class name (with namspace) for the schema id.
Program.cs |
builder.Services.AddSwaggerGen(options =>
{
options.CustomSchemaIds(type => type.ToString());
});
|
Url
Url | Resource |
---|---|
http://localhost:<port>/swagger | swagger UI |
http://localhost:<port>/swagger/v1/swagger.json | swagger json |
Dans un projet Web API avec Visual Studio Code, ouvrir le navigateur sur la page swagger.
.vscode\launch.json |
{
"configurations": [
{
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger"
},
// autre solution
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}/swagger/index.html?url=/swagger/v1/swagger.json#!/Items"
}
}
|
Paramètres optionnels
Swagger ne gère pas les paramètres optionnels s'ils font partie du chemin, il les considère comme des paramètres required.