Skip to content

Support all ProblemDetail types in the multi response types for generating swagger docs MinimalApi #47623

Closed
@mehdihadeli

Description

@mehdihadeli

Hi,
I want to create an api with multiple result types with using TypedResults, but seems, .net core 7 only supports ValidationProblem for generating swagger metadata automatically and ProblemHttpResult type doesn't generate any swagger metadata. Maybe we need to declare dedicated problem types like ValidationProblem for others, like InternalProbelm, UnAuthorizedProblem, ...

      async Task<Results<CreatedAtRoute<CreateProductResponse>, ProblemHttpResult>>
            Handle([AsParameters] CreateProductRequestParameters requestInput)
        {
            ///...
            return TypedResults.CreatedAtRoute(
                new CreateProductResponse(result.Id),
                "GetProductById",
                new {id = result.Id});
        }

I had to handle it manually for myself like this (we have some limitation because ProblemHttpResult is sealed class and I can't inherit from it directly, so I created a HttpProblemResultBase for replacement, also ProducesResponseTypeMetadata was internal, and I had to create a custom one):

public class HttpProblemResultBase :
    IResult,
    IStatusCodeHttpResult,
    IContentTypeHttpResult,
    IValueHttpResult,
    IEndpointMetadataProvider,
    IValueHttpResult<ProblemDetails>
{
    private readonly ProblemHttpResult _problem;

    public HttpProblemResultBase(
        int statusCode,
        string? title = null,
        string? type = null,
        string? detail = null,
        string? instance = null,
        IDictionary<string, object?>? extensions = null
    )
    {
        _problem = TypedResults.Problem(
            statusCode: statusCode,
            title: title,
            type: type,
            detail: detail,
            instance: instance,
            extensions: extensions);
    }

    public Task ExecuteAsync(HttpContext httpContext)
    {
        return _problem.ExecuteAsync(httpContext);
    }

    public ProblemDetails ProblemDetails => _problem.ProblemDetails;
    public virtual int? StatusCode => _problem.StatusCode;
    public string ContentType => _problem.ContentType;
    object IValueHttpResult.Value => ProblemDetails;
    public ProblemDetails Value => ProblemDetails;

    public static void PopulateMetadata(MethodInfo method, EndpointBuilder builder)
    {
        method.NotNull();
        builder.NotNull();
        builder.Metadata.Add(new ResponseMetadata(StatusCodes.Status500InternalServerError, typeof(ProblemDetails)));
    }
}

public class InternalHttpProblemResult : HttpProblemResultBase
{
    public InternalHttpProblemResult(
        string? title = null,
        string? type = null,
        string? detail = null,
        string? instance = null,
        IDictionary<string, object?>? extensions = null
    ) : base(StatusCodes.Status500InternalServerError, title, type, detail, instance, extensions)
    {
    }
}

public class NotFoundHttpProblemResult : HttpProblemResultBase
{
    public NotFoundHttpProblemResult(
        string? title = null,
        string? type = null,
        string? detail = null,
        string? instance = null,
        IDictionary<string, object?>? extensions = null
    ) : base(StatusCodes.Status404NotFound, title, type, detail, instance, extensions)
    {
    }
}

And my route now should be for generating swagger metadata for problems automatically:

      async Task<Results<CreatedAtRoute<CreateProductResponse>, UnAuthorizedHttpProblemResult, ValidationProblem>>
            Handle([AsParameters] CreateProductRequestParameters requestInput)
        {
            ///...
            return TypedResults.CreatedAtRoute(
                new CreateProductResponse(result.Id),
                "GetProductById",
                new {id = result.Id});
        }

Metadata

Metadata

Assignees

Labels

✔️ Resolution: By DesignResolved because the behavior in this issue is the intended design.Status: Resolvedarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions