Skip to content

Update to Microsoft.OpenApi v2.0.0-preview.17 #61541

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

Merged
merged 5 commits into from
Apr 24, 2025
Merged

Conversation

captainsafia
Copy link
Member

@captainsafia captainsafia commented Apr 17, 2025

  • React to nullable annotations changes in types
  • React to OperationType -> HttpMethod move
  • React to Annotations -> Metadata rename
  • React to discriminator mapping using OpenApiSchemaReference
  • React to Reader package being renamed to YamlReader

@captainsafia captainsafia requested review from a team and wtgodbe as code owners April 17, 2025 21:46
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Apr 17, 2025
@captainsafia captainsafia added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Apr 17, 2025
@@ -661,7 +677,7 @@ private async Task<OpenApiRequestBody> GetFormRequestBody(
var contentType = requestFormat.MediaType;
requestBody.Content[contentType] = new OpenApiMediaType
{
Schema = schema
Schema = complexTypeSchema ?? schema
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not following this change. Can you explain it? And does it need a new test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working a bit around some of the new strictness in the APIs. The IOpenApiSchema has two implementations OpenApiSchema which represents a resolved schema and has set/get on all properties and OpenApiSchemaaReference which is a pointer to a schema and only exposes a get on properties.

The schema variable represents a resolved schema that we construct and populate with form parameters depending on some specific rules. For example, if you have multiple parameters annotated with [FromForm] like in this test we generate a schema that uses allOf to indicate that all of the properties in each type should appear in a single form payload.

When there is a single parameter annotated with [FromForm] and it is a complex type then the binding implementation resolves from its properties directly. This test validates that behavior.

@@ -383,6 +387,29 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform

return Task.CompletedTask;
}

private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this - I might borrow it for Swashbuckle 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm -- I wonder if it might be worth integrating into the Microsoft.OpenAPI APIs? Let me know how it shakes out for you in practice and we can consider moving it to the base library?

"PATCH" => HttpMethod.Patch,
"HEAD" => HttpMethod.Head,
"OPTIONS" => HttpMethod.Options,
"TRACE" => HttpMethod.Trace,
_ => throw new InvalidOperationException($"Unsupported HTTP method: {apiDescription.HttpMethod}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC there's a bug logged somewhere about an exception being throw for the empty string in MVC instead of being a GET. If you're touching this area maybe fix that here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the right fix for that bug is to fix the ApiExplorer layer so that GET is the assumed default for MVC controller actions that don't explicitly set it. That way we can retain the behavior of throwing for actually invalid HTTP methods here.

HttpMethod.Options,
HttpMethod.Head,
HttpMethod.Patch,
HttpMethod.Trace
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen an issue that there's a new QUERY method coming soon, so that might need adding shortly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, the OpenAPI spec doesn't yet support all HTTP methods. There's been discussion of loosening this requirement in the past but at the moment it only supports this fixed set.

@@ -31,17 +31,25 @@ public void MapRelativePathToItemPath_ReturnsItemPathForApiDescription(string re
Assert.Equal(expectedItemPath, itemPath);
}

public static class HttpMethodTestData
{
public static IEnumerable<object[]> TestCases => new List<object[]>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding my comment about QUERY, is it worth adding a reflection-based test that checks for HttpMethod having any new static property to flush out the need to react to any addition?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can probably forgo on this until the spec supports more HTTP methods. From my understanding, moving from OperationType to HttpMethod in this breaking change was a setup for that.

@@ -407,7 +407,7 @@ private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceP
}
else
{
throw new InvalidOperationException("The input schema must be an OpenApiParameter or OpenApiParameterReference.");
throw new InvalidOperationException("The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new InvalidOperationException("The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg I hate myself

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one did make me feel bad 😅 when I spotted it in the snapshots

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's ok I groaned harder on the other whitespace issue

I really wish there was a nicer templating story for source generated files so you could catch these kinds of things more easily

@@ -338,6 +338,8 @@ await VerifyOpenApiDocument(action, document =>
[([MinLength(2)] int[] id) => {}, (OpenApiSchema schema) => Assert.Equal(2, schema.MinItems)],
[([Length(4, 8)] int[] id) => {}, (OpenApiSchema schema) => { Assert.Equal(4, schema.MinItems); Assert.Equal(8, schema.MaxItems); }],
[([Range(4, 8)]int id) => {}, (OpenApiSchema schema) => { Assert.Equal("4", schema.Minimum); Assert.Equal("8", schema.Maximum); }],
[([Range(1234, 5678)]int id) => {}, (OpenApiSchema schema) => { Assert.Equal("1234", schema.Minimum); Assert.Equal("5678", schema.Maximum); }],
[([Range(1234.56, 7891.1)] decimal id) => {}, (OpenApiSchema schema) => { Assert.Equal("1234.56", schema.Minimum); Assert.Equal("7891.1", schema.Maximum); }],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[([Range(1234.56, 7891.1)] decimal id) => {}, (OpenApiSchema schema) => { Assert.Equal("1234.56", schema.Minimum); Assert.Equal("7891.1", schema.Maximum); }],
[([Range(1234.56, 7891.1)] decimal id) => {}, (OpenApiSchema schema) => { Assert.Equal("1234.56", schema.Minimum); Assert.Equal("7891.1", schema.Maximum); }],

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:groan:

@martincostello
Copy link
Member

I'm guessing this missed the ⛵ for preview 4?

@BrennanConroy
Copy link
Member

I'm guessing this missed the ⛵ for preview 4?

Oh, yeah, it's too late unless we really need it. I should have merged it for her since she's out...

@martincostello
Copy link
Member

martincostello commented Apr 24, 2025

It would be nice as there's a big dependency chain for stuff like Swashbuckle.AspNetCore where we can't use newer previews of Microsoft.OpenApi due to various binary-breaking changes along the way since p11, so without it we can't test anything newer until June (domaindrivendev/Swashbuckle.AspNetCore#3283 (comment))

@BrennanConroy BrennanConroy merged commit bc1b3b2 into main Apr 24, 2025
27 checks passed
@BrennanConroy BrennanConroy deleted the safia/openapi-p4-bump branch April 24, 2025 19:04
@BrennanConroy
Copy link
Member

/backport to release/10.0-preview4

Copy link
Contributor

Started backporting to release/10.0-preview4: https://github.com/dotnet/aspnetcore/actions/runs/14649645511

@dotnet-policy-service dotnet-policy-service bot added this to the 10.0-preview5 milestone Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants