I have a generic Result<T>
response type in my controllers, e.g.
public Result<T> GetSomething()
{
...
}
I also have a custom asp.net core filter that returns a Json representation of T
To have swashbuckle generate correct documentation, I have to decorate every method with:
[Produces(typeof(T))]
As this is cumbersome, easily forgotten and error prone, I was looking for a way to automate this.
Now in Swashbuckle you have a MapType
, but I can't get a hold of the T
in those methods:
services.AddSwaggerGen(c =>
{
...
c.MapType(typeof(Result<>), () => /*can't get T here*/);
};
I was looking at the IOperationFilter
but I can't find a way to override the result type in there.
Then there are ISchemaFilter
public class ResultSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (!context.Type.IsGenericType || !context.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Result<>)))
{
return;
}
var returnType = context.Type.GetGenericArguments()[0];
//How do I override the schema here ?
var newSchema = context.SchemaGenerator.GenerateSchema(returnType, context.SchemaRepository);
}
}
IOperationFilter
is the correct choice. Here is an example that changes the response type for OData endpoints.
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
//EnableQueryAttribute refers to an OData endpoint.
if (context.ApiDescription.ActionDescriptor.EndpointMetadata.Any(em => em is EnableQueryAttribute))
{
//Fixing the swagger response for Controller style endpoints
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor cad)
{
//If the return type is IQueryable<T>, use ODataResponseValue<T> as the Swagger response type.
var returnType = cad.MethodInfo.ReturnType;
if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IQueryable<>))
{
var actualType = returnType.GetGenericArguments()[0];
var responseType = typeof(ODataResponseValue<>).MakeGenericType(actualType);
var schema = context.SchemaGenerator.GenerateSchema(responseType, context.SchemaRepository);
foreach (var item in operation.Responses["200"].Content)
item.Value.Schema = schema;
}
}
}
}
As you can see here, I'm looping through all of the items in operation.Responses["200"].Content
, replacing their schema one by one using the GenerateSchema
method that you found.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With