Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider returning reference type from AddComponent API #2162

Open
captainsafia opened this issue Feb 24, 2025 · 3 comments
Open

Consider returning reference type from AddComponent API #2162

captainsafia opened this issue Feb 24, 2025 · 3 comments
Milestone

Comments

@captainsafia
Copy link
Member

The AddComponent API currently returns a boolean that indicates if the addition of the component to the document registry succeeded.

It would be nice if the API returned a reference to the item that was just constructed. In an M.A.OpenAPI transformer, I currently need to write:

options.AddOperationTransformer((operation, context, cancellationToken) =>
{
    var schemaService = context.ApplicationServices.GetRequiredKeyedService<IOpenApiSchemaService>(context.DocumentName);
    if (context.Description.RelativePath == "error")
    {
        var errorSchema = schemaService.GetOrCreateSchema(typeof(ProblemDetails));
        context.Document.AddComponent("Error", errorSchema);
        operation.Responses["500"] = new OpenApiResponse
        {
            Description = "Error",
            Content =
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = new OpenApiSchemaReference("Error", context.Document),
                },
            },
        };
    }
    return Task.CompletedTask;
});

but would like to write:

options.AddOperationTransformer((operation, context, cancellationToken) =>
{
    var schemaService = context.ApplicationServices.GetRequiredKeyedService<IOpenApiSchemaService>(context.DocumentName);
    if (context.Description.RelativePath == "error")
    {
        var errorSchema = schemaService.GetOrCreateSchema(typeof(ProblemDetails));
        var insertedSchema = context.Document.AddComponent("Error", errorSchema);
        operation.Responses["500"] = new OpenApiResponse
        {
            Description = "Error",
            Content =
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = insertedSchema,
                },
            },
        };
    }
    return Task.CompletedTask;
});

cc: @baywet I couldn't see if an API that did this existed already and figured I'd add the proposal.

@baywet
Copy link
Member

baywet commented Feb 24, 2025

Hi @captainsafia
We do have constructors overloads that are internal at the moment and would allow you to pass the source schema directly.
Effectively allowing you to write something like this

options.AddOperationTransformer((operation, context, cancellationToken) =>
{
    var schemaService = context.ApplicationServices.GetRequiredKeyedService<IOpenApiSchemaService>(context.DocumentName);
    if (context.Description.RelativePath == "error")
    {
        var errorSchema = schemaService.GetOrCreateSchema(typeof(ProblemDetails));
        context.Document.AddComponent("Error", errorSchema);
        operation.Responses["500"] = new OpenApiResponse
        {
            Description = "Error",
            Content =
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = new OpenApiSchemaReference("Error", insertedSchema, document),
                },
            },
        };
    }
    return Task.CompletedTask;
});

I'm not saying this would be better than your proposal, just stating it's a possibility.

I think it'd be preferable to separate the two concerns, and offer something like that instead.

options.AddOperationTransformer((operation, context, cancellationToken) =>
{
    var schemaService = context.ApplicationServices.GetRequiredKeyedService<IOpenApiSchemaService>(context.DocumentName);
    if (context.Description.RelativePath == "error")
    {
        var errorSchema = schemaService.GetOrCreateSchema(typeof(ProblemDetails));
        var schemaId = "error";
        context.Document.AddComponent(schemaId, errorSchema);
        operation.Responses["500"] = new OpenApiResponse
        {
            Description = "Error",
            Content =
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = context.Document.GetReferenceForComponent(schemaId),
                },
            },
        };
    }
    return Task.CompletedTask;
});

(which would return a value or throw, we could also have a TryGet variant)
what do you think?

@baywet baywet added this to the v2-Preview11 milestone Feb 24, 2025
@captainsafia
Copy link
Member Author

I think it'd be preferable to separate the two concerns, and offer something like that instead.

Why do you think its preferable to separate?

IMO, having the AddComponent API makes it a little easier to connect the fact that the object that is inserted into a Schema property is a reference to the thing that was added to components. The two concepts seem linked in that way to me.

@baywet
Copy link
Member

baywet commented Feb 25, 2025

Because:

  1. One might want to create multiple references to the same component.
  2. One might not want to create the reference at the same time the component is added, in which case the allocation is wasted (depending on how we model the overloads)

@RachitMalik12 RachitMalik12 modified the milestones: v2-Preview12, v2-postGA Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants