Description
Background and Motivation
The current OpenAPI implementation in ASP.NET Core lacks support for being able to dynamically generate OpenAPI schemas and insert them into the document. Without built-in APIs for this, evelopers must manually write the schemas for types in their application that need to be referenced automatically. While this can be straightforward for simple types, it grows complicated for DTOs and more complex types in the user application. Furthermore, developers can't take advantage of the built-in logic the OpenAPI implementation has to support resolving metadata from ParameterInfo
and route constraints.
- The
GetOrCreateSchema
API takes a type and an ApiParameterDescription to support being able to generate schemas for the type and apply any metadata from theParameterInfo
to it. - The
Document
property is added to the transformer contexts to allow users to interact with the components store, provided by the underlyingMicrosoft.OpenApi
library.
Proposed API
namespace Microsoft.AspNetCore.OpenApi;
+public interface IOpenApiSchemaProvider
+{
+ OpenApiSchema GetOrCreateSchema(System.Type type, Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterDescription? parameterDescription = null);
+}
public class OpenApiDocumentTransformerContext : IOpenApiSchemaProvider
{
+ public OpenApiSchema GetOrCreateSchema(System.Type type, Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterDescription? parameterDescription = null);
}
public class OpenApiOperationTransformerContext : IOpenApiSchemaProvider
{
+ public Microsoft.OpenApi.Models.OpenApiDocument Document { get; init; }
+ public OpenApiSchema GetOrCreateSchema(System.Type type, Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterDescription? parameterDescription = null);
}
public class OpenApiSchemaTransformerContext : IOpenApiSchemaProvider
{
+ public Microsoft.OpenApi.Models.OpenApiDocument Document { get; init; }
+ public OpenApiSchema GetOrCreateSchema(System.Type type, Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterDescription? parameterDescription = null);
}
Usage Examples
builder.Services.AddOpenApi("v1", options =>
{
options.AddOperationTransformer((operation, context, cancellationToken) =>
{
// Generate schema for error responses
var errorSchema = context.GetOrCreateSchema(typeof(ProblemDetails));
context.Document.AddComponent("Error", errorSchema);
// Reference the schema in responses
operation.Responses["500"] = new OpenApiResponse
{
Description = "Error",
Content =
{
["application/problem+json"] = new OpenApiMediaType
{
Schema = new OpenApiSchemaReference("Error", context.Document)
}
}
};
return Task.CompletedTask;
});
});
Alternative Designs
N/A
Design Notes
The IOpenApiSchemaProvider
type is not applied on the OpenApiSchemaService
registered in the DI container. We opted not to do this in favor of restricting schema generation to the transformer APIs. This avoids the Microsoft.AspNetCore.OpenApi
package becoming a generic schema generation API and allows us to limit the functionality to codepaths that we have more control over (OpenAPI document transformers).
Schema transformers registered in an API are applied to schemas that are generated by the service. This can increase the risk for re-entrant or recursive schema transformers to generate too many schemas if developers do not add guards against these cases.
Risks
- The new APIs are additions with no breaking changes to existing functionality.
- Performance impact should be minimal as schema generation is typically done once during startup or on-demand.
- The implementation only exposes APIs for generating schemas, the schema store is modeled directly on the OpenAPI document which is handled by a third-party API.