I have the following Response object:
public class Response<T> where T : ResponseData
{
public bool Success { get; set; }
public HttpStatusCode StatusCode { get; set; }
public string ErrorCode { get; set; }
public string ErrorDescription { get; set; }
public T Data { get; set; }
public Response(bool success, HttpStatusCode statusCode, string errorCode, string msg, T data = null)
{
Success = success;
StatusCode = statusCode;
ErrorCode = errorCode;
ErrorDescription = msg;
Data = data;
}
The ResponseData class is just a base class:
public class ResponseData
{
}
Then I have for example the following class:
public class ResponseProduct: ResponseData
{
public int Id{ get; set; }
public string Description { get; set; }
}
On my controller I have the following:
[HttpGet]
[Route(ApiBaseConstants.MethodProduct)]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(typeof(Response<ResponseProduct>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetProduct()
{
return ParseResponse(await CurrentApi.GetProduct());
}
The problem I have is that it doesn't generate on the schema the Response object instead it generates a ResponseProductResponse which is the Response< ResponseProduct > so I have the following schemas:
How can I have a Response instead of a ResponseProductResponse?
well , adding an SchemaFilter would work
public class ResponseTypeSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsGenericType && context.Type.GetGenericTypeDefinition() == typeof(Response<>))
{
var responseType = context.Type.GetGenericArguments()[0];
if (responseType.IsGenericType && responseType.GetGenericTypeDefinition() == typeof(List<>))
{
var itemType = responseType.GetGenericArguments()[0];
var itemSchema = context.SchemaGenerator.GenerateSchema(itemType, context.SchemaRepository);
schema.Type = "array";
schema.Items = itemSchema;
}
else
{
schema.Reference = null;
schema.Properties.Clear();
schema.Type = "object";
var props = responseType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
schema.Properties[prop.Name] = context.SchemaGenerator.GenerateSchema(prop.PropertyType, context.SchemaRepository);
}
}
}
}
}
and configure your swagger like
services.AddSwaggerGen(swaggerOptions =>
{
swaggerOptions.SchemaFilter<ResponseTypeSchemaFilter>();
});