Skip to content

[release/7.0-rc1] Add support for running final conventions during build #43225

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
Aug 18, 2022

Conversation

captainsafia
Copy link
Member

@captainsafia captainsafia commented Aug 11, 2022

Description

This PR adds support for running conventions on an endpoint builder after "standard conventions" have been run. This allows these conventions to inspect metadata that has been registered by standard conventions and react to it. In particular, it allows groups to examine metadata of their endpoints.

Addresses #42750

Customer Impact

The changes in this PR address a bug that made it impossible for users to leverage the route groups feature, WithOpenApi, and metadata annotations on their endpoints.

var clients = app.MapGroup("/clients/{id}")
  .WithOpenApi();

clients.MapGet("/", () => ...)
  .Produces<Client>(); // Annotation doesn't appear in OpenApi definition without this change

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Low risk because:

  • Changes is limited to ASP.NET Core surface area
  • Change is only used in APIs introduced in .NET 7
  • Change is additive and doesn't alter existing behavior

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

@davidfowl
Copy link
Member

This change looks nice

@captainsafia captainsafia force-pushed the safia/finally branch 2 times, most recently from cc1c059 to 2841f94 Compare August 12, 2022 15:56
@Pilchie Pilchie added the old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Aug 12, 2022
/// Registers the specified convention for execution after the target builder has been built.
/// </summary>
/// <param name="finalConvention">The final convention to add to the builder.</param>
void Finally(Action<EndpointBuilder> finalConvention) => throw new NotImplementedException();
Copy link
Member

Choose a reason for hiding this comment

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

Are we worried that making the default method throw will break existing scenarios? Basically, anywhere in the framework where we now call Finally, is the IEndpointConventionBuilder potentially a user defined one? And if so, was the code path accessible prior to 7.0?

Copy link
Member Author

Choose a reason for hiding this comment

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

Are we worried that making the default method throw will break existing scenarios?

This is a new API so I'm not too anxious about it breaking existing scenarios and the one place where it is used is WithOpenApi which was introduced in 7.0.

Basically, anywhere in the framework where we now call Finally, is the IEndpointConventionBuilder potentially a user defined one?

Yep, I've added implementations in all the IEndpointConvenntionBuilder implementations except those that are used for tests:

  • ComponentEndpointConventionBuilder
  • RouteHandlerBuilder
  • ConnectionEndpointRouteBuilder
  • RouteGroupBuilder
  • HubEndpointConventionBuilder
  • ControllerActionEndpointConventionBuilder
  • PageActionEndpointConventionBuilder

Copy link
Member

Choose a reason for hiding this comment

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

Do a grep.app on github.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do a grep.app on github.

YARP and gRPC also have implementations of IEndpointConventionBuilder, so we'll want to implement Finally there too.

However, at least for the time being, there's no risk of breaking existing scenarios in those APIs since they don't use it currently.

Copy link
Member

Choose a reason for hiding this comment

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

It's not about gPRC or YARP or anyone elses implementation using Finally, it's about our code calling Finally on them.

Copy link
Member

Choose a reason for hiding this comment

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

only place that might call into their Finally

Ok, that's what I was asking without knowing how to ask it 👍

Copy link
Member

Choose a reason for hiding this comment

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

Given that WithOpenApi already skips over non RouteEndpointBuilder endpoints and endpoints without MethodInfo metadata, skipping over unsupported endpoints is already a behavior. Should we swallow the NotImplemented exception from Finally in WithOpenApi? Also, I don't like finalConvention because it implies there can only be one of them.

Suggested change
void Finally(Action<EndpointBuilder> finalConvention) => throw new NotImplementedException();
void Finally(Action<EndpointBuilder> finallyConvention) => throw new NotImplementedException();

Copy link
Member Author

Choose a reason for hiding this comment

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

Should we swallow the NotImplemented exception from Finally in WithOpenApi?

I'm not too enthused about treating the exception thrown here as some sort of contract that WithOpenApi will check for.

endpoints without MethodInfo metadata,

It doesn't generate an operation for these types of endpoints but the Finally convention will still be registered on them so it's not totally the same.

Also, I don't like finalConvention because it implies there can only be one of them.

Bleh. This wan't intentional. I used VS Code to do a find/replace of final => finally in the src/Http and src/Mvc directories but it looks like this one might've been skipped. :/

Copy link
Member

Choose a reason for hiding this comment

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

Or maybe just call it convention because that also makes sense 😄. The property should be final conventions and the parameter should be convention. They are both adding conventions that run a different times.

Copy link
Member

Choose a reason for hiding this comment

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

Imagine this was an abstract base class, the options are:

  • Add a bool SupportsFinally, return false by default, make the new virtual member throw, or have a reasonable implementation (like calling Add?)

@captainsafia
Copy link
Member Author

585e4ec contains the following:

  • Fixes the typo in the renames for "finally conventions"
  • Updates RouteGroupBuilder, RouteEndpointDataSource, and ActionEndpointDataSource implementations to use Stack to represent "finally conventions"
  • Remove reversals and reverse-iterations in Build implementations

- Fix ordering of group and entry-specific conventions in parameter list
- Update to use FIFO ordering within finally conventions of the same level
- Add tests for WithOpenApi on group and endpoint
- Revert to using List instead of Stack for convention
- Fix ordering of outer and inner group in RouteGroups
@captainsafia
Copy link
Member Author

3f1e1cd includes the following:

  • Fix ordering of group and entry-specific conventions in parameter list
  • Update to use FIFO ordering within finally conventions of the same level
  • Add tests for WithOpenApi on group and endpoint
  • Revert to using List instead of Stack for convention
  • Fix ordering of outer and inner group in RouteGroups

@captainsafia captainsafia changed the base branch from main to release/7.0-rc1 August 17, 2022 18:14
@captainsafia captainsafia added the Servicing-consider Shiproom approval is required for the issue label Aug 17, 2022
@ghost
Copy link

ghost commented Aug 17, 2022

Hi @captainsafia. Please make sure you've updated the PR description to use the Shiproom Template. Also, make sure this PR is not marked as a draft and is ready-to-merge.

To learn more about how to prepare a servicing PR click here.

Copy link
Member

@halter73 halter73 left a comment

Choose a reason for hiding this comment

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

:shipit: (Maybe remove required from RouteGroupContext.Prefix though).

@captainsafia captainsafia changed the title Add support for running final conventions during build [release/7.0-rc1] Add support for running final conventions during build Aug 17, 2022
@leecow leecow added Servicing-approved Shiproom has approved the issue and removed Servicing-consider Shiproom approval is required for the issue labels Aug 18, 2022
@captainsafia
Copy link
Member Author

@dotnet/aspnet-admins Can I get help merging this?

Failing code check is because this PR introduces new APIs. 🙊

@wtgodbe wtgodbe merged commit 006d96f into release/7.0-rc1 Aug 18, 2022
@wtgodbe wtgodbe deleted the safia/finally branch August 18, 2022 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels Servicing-approved Shiproom has approved the issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants