Closed icnocop closed 1 year ago
Hello, sorry for the delay. Can you elaborate more on what this PR tries to achieve? All I see is code duplicity that is not wired up to the existing logic. If I understand the issue correctly, you just want to have option to specify one or many examples for specific API endpoint, is that correct?
Right, the code allows defining one or more request and response examples specific to an API endpoint, and for each response code, much like https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters, so they show up in swagger UI.
Usage:
In Startup.cs, in ConfigureServices, add ExamplesOperationProcessor:
services.AddOpenApiDocument((settings, serviceProvider) =>
{
var jsonSerializerSettings = serviceProvider.CreateScope().ServiceProvider.GetService<JsonSerializerSettings>();
var examplesConverter = new ExamplesConverter(jsonSerializerSettings);
var examplesOperationProcessor = new ExamplesOperationProcessor(examplesConverter, serviceProvider);
settings.OperationProcessors.Add(examplesOperationProcessor);
}
In controller, decorate method with attributes:
[ApiController]
Route("api/[controller]")]
public class PetsController : ControllerBase
{
[HttpPost]
[OpenApiRequestExample(typeof(CreatePetRequest), typeof(CreatePetRequestExample))] // example request
[OpenApiResponseExample(StatusCodes.Status201Created, typeof(CreatePetResponseExample))] // example response
public IActionResult Post([FromBody] CreatePetRequest request)
{
// process request and return response
return Created(newPet);
}
}
Define examples:
public class CreatePetRequestExample : IOpenApiExampleProvider<CreatePetRequest>
{
public override CreatePetRequest GetExample()
{
return new CreatePetRequest
{
Name = "Cupcake",
Tag = "Chihuahua"
};
}
}
public class CreatePetResponseExample : IOpenApiExampleProvider
To return more than one example, inherit from `IOpenApiExamplesProvider<T>` and override `GetExamples` instead:
public class CreatePetRequestExamples : IOpenApiExamplesProvider
yield return new OpenApiExample<CreatePetRequest>(
"sample2",
new CreateItemRequest
{
Name = "Prince",
Tag = "Poodle"
});
}
}
The request and response examples will show up in swagger UI in a drop down menu, as illustrated here:
https://www.viralpatel.net/openapi-multiple-examples/
![image](https://user-images.githubusercontent.com/507649/206894679-76ead4a7-6523-4ac7-bf6d-78ff8225692e.png)
![image](https://user-images.githubusercontent.com/507649/206894681-6241be5b-b53e-4e54-b2a1-666d25fc7fc2.png)
This looks pretty useful, @icnocop , especially when you work with complex APIs that might have polymorphic request models; my only thought is that maybe it would be simpler just to have the one interface to implement (IOpenApiExamplesProvider<CreatePetRequest>
in your example), and if the enumerable returns a single value then treat it as you would the singular interface IOpenApiExampleProvider<CreatePetRequest>
? That way, if you decide that you do need to provide multiple examples, you preserve SRP by adding the new example model to the provider and don't need to change the interface the provider implements.
Maybe this should be a new method on the existing IExampleProvider<T>
, because I rather like the approach that that takes where it keys off the ASP.NET MVC ProducesResponseType
attribute rather than requiring an NSwag-specific attribute? It might play more nicely with code generation too.
Does any of that make sense, @vaclavnovotny ?
Sorry for the very prolonged delay.
@davidkeaveny I agree, I see value in providing more examples per endpoint, for example when polymorphism is used.
However, as you mentioned, I would stay with the standard ProducesResponseType
and add support for multiple T
instances from IExampleProvider<T>
.
@davidkeaveny if you want go ahead and implement it, otherwise I will look into it.
Hello @icnocop, based on this PR I have added the requested features to the release 1.0.9. It needed to be reimplemented so it uses the standard ASP.NET ProducesResponseType attribute. Please check the documentation and try it. In case of any problems, please create an issue. Cheers.
Fixes #8