domaindrivendev / Swashbuckle.AspNetCore

Swagger tools for documenting API's built on ASP.NET Core
MIT License
5.22k stars 1.31k forks source link

How to solve SwaggerGeneratorException with the same HTTP method, endpoint and parameters but consumes different Content-Type? #2354

Open csf-andyliao opened 2 years ago

csf-andyliao commented 2 years ago

For reasons, I need expose some API endpoints with the same HTTP method and parameters to support different Content-Type.

With [ApiController] attribute, I always got http error 415 Unsupported Media Type when I send data by setting application/x-www-form-urlencoded.

I found a solution like sample code as below. But I got SwaggerGeneratorException when I distribute swagger.json to my team, how to solve this?

Sample code

[HttpPost]
[Route("~/api/v1/Test")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult ByForm ([FromForm] TestViewModel vm) => Do(vm);

[HttpPost]
[Route("~/api/v1/Test")]
[Consumes("application/json")]
public IActionResult ByJson ([FromBody] TestViewModel vm) => Do(vm);

private IActionResult Do(TestViewModel vm)
{
    // ... Do something and return result.
}

Expected Get swagger.json successfully.

Actual

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Conflicting method/path combination "POST api/v1/Test" for actions - TestProject.Controllers.TestController.ByForm (TestProject),TestProject.Controllers.TestController.ByJson (TestProject). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Version 6.2.3

Yortw commented 2 years ago

I have the same problem. I need a single end point which accepts different content types as input. The .Net API/routing system is perfectly happy with this, it works, but Swagger fails to generate the json file required for the docs. I've read that the OpenAPI 2.0 specification doesn't actually support this, but 3.0 does. Not sure which version is currently being used, but maybe that's part of the problem?

Dirk-Peters-BF commented 1 year ago

Same problem here. Routing with asp.net core works perfectly fine, HTTP and OpenAPI 3.0 specification allow routing based on different media types, but saschbuckle does not accept same paths with different consumed media types. Last time I checked, the swagger implementation for Quarkus does.

kcrandall commented 8 months ago

I'm having the same problem but for [Produces] of different content types

github-actions[bot] commented 4 months ago

This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.

martincostello commented 4 months ago

Is this still an issue with 6.5.0 when generating OpenAPI 3.0?

Yortw commented 4 months ago

Hi,

We have a .Net Core Web API project, targeting .Net 6, and with the following package versions:

I am not sure how to determine if it is specifically generating an OpenAPI 3.0 result, if you're able to tell me how to check I can and get back to you.

Assuming using those package versions should default to OpenPAI 3.0 output, then yes, this is still a problem.

We currently have our startup process configuring swagger to just take the first definition to avoid the error, and get any docs generated. That code looks something like:

services.AddSwaggerGen ( (c) => { c.ResolveConflictingActions((apis) => apis.First()); } );

Once I removed that to revert to the standard behaviour, so the system should generate content for each endpoint & accept/content type combination I get an 500 error result through the docs UI:

image

If I look at the output window in Visual Studio, I can see the following exception being reported. This looks some part of the system is still considering an endpoint to be unique solely based on the path, and not looking at the accept/content types. 14:34:11:605 Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Conflicting method/path combination "POST v1/devices/registrations" for actions - x.Api.Controllers.DeviceRegistrationController.RequestDeviceRegistration (x.Api),x.Api.Controllers.DeviceRegistrationController.ProcessDeviceRegistration (x.Api). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround 14:34:11:605 at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable1 apiDescriptions, SchemaRepository schemaRepository) 14:34:11:605 at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable1 apiDescriptions, SchemaRepository schemaRepository) 14:34:11:605 at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerDocumentWithoutFilters(String documentName, String host, String basePath) 14:34:11:605 at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(String documentName, String host, String basePath) 14:34:11:605 at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) 14:34:11:605 at x.Api.CompressedRequestMiddleware.Invoke(HttpContext context) in C:\Projects\work\x\Api\GzipRequestMiddleware.cs:line 31 14:34:11:605 at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Please let me know if I've missed anything obvious or there's more detail I can provide.