Skip to content

Remove RequestDelegateFactory call from RouteEndpointBuilder #42827

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 10 commits into from
Aug 6, 2022

Conversation

halter73
Copy link
Member

@halter73 halter73 commented Jul 19, 2022

  • Remove ModelEndpointDataSource. Use RouteEndpointDataSource instead
  • Filters will no longer run for razor pages due to this change.

This is somewhat dependent on #42557 to ensure we have a nice experience where "endpoint" filters run on both route handlers, normal RequestDelegates and MVC actions.

Fixes #42703

- Remove ModelEndpointDataSource. Use RouteEndpointDataSource instead
@halter73 halter73 requested a review from javiercn as a code owner July 19, 2022 22:03
@ghost ghost added the area-runtime label Jul 19, 2022
// Add MethodInfo and HttpMethodMetadata (if any) as first metadata items as they are intrinsic to the route much like
// the pattern or default display name. This gives visibility to conventions like WithOpenApi() to intrinsic route details
// (namely the MethodInfo) even when applied early as group conventions.
builder.Metadata.Add(handler.Method);
Copy link
Member

Choose a reason for hiding this comment

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

I think we want to add this in either case so open api works.

Copy link
Member

Choose a reason for hiding this comment

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

I think adding it only for route handlers will actually help with our goal of making WithOpenApi something you can only apply on RouteHandlerBuilder types even though we removed that constraint. AFAIK, non-route handler scenarios don't need access to the method info.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's the question. Do we want OpenAPI for these endpoints or not? What if someone manually adds [Consumes] or [Produces] metadata to these endpoints? For now, I'm trying to keep this behavior consistent with the behavior we've already have.

Copy link
Member

Choose a reason for hiding this comment

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

I think we should unify these endpoints mostly because of the amount of bugs where people end up calling the RequestDelegate overload and it things stop working.

Comment on lines 233 to 234
Assert.Equal("METHOD", GetMethod(endpoint.Metadata[0]));
Assert.Equal("ATTRIBUTE", GetMethod(endpoint.Metadata[1]));
Copy link
Member

Choose a reason for hiding this comment

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

Breaking change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Technically.

You'd had to have defined a custom attribute that implemented IHttpMethodMetadata which no one on grepp.app has other than us in this very test, in one other test which notably didn't need to be changed because it wasn't overriding anything, and in .NET 6 preview diffs before I removed it from the MVC attributes. We certainly don't ship any such attributes.

Plus, we already made this "breaking" change for route handlers between .NET 6 and .NET 7 with #40926. See https://github.com/dotnet/aspnetcore/pull/40926/files#diff-f6727c82b3f6cff19c30c9c793f3e47c1c2ff2035a6453198ff4cedad8e84557

I almost went the other way and had RouteEndopintDataSource copy the old .NET 6 behavior here so we didn't "break" anything for either Delegate or RequestDelegate, but it makes sense to configure metadata added implicitly by the MapXxx call like the MethodInfo and HttpMethodMetadata before any additional metadata configured by the user.

@javiercn
Copy link
Member

Filters will no longer run for razor pages due to this change.

This might be problematic as it will break people's expectations that these filters run in both cases like other MVC filters. Is there a specific reason to prevent these filters from applying to pages?

Co-authored-by: Kahbazi <[email protected]>
Co-authored-by: David Fowler <[email protected]>
@halter73
Copy link
Member Author

halter73 commented Jul 22, 2022

Filters will no longer run for razor pages due to this change.

This might be problematic as it will break people's expectations that these filters run in both cases like other MVC filters. Is there a specific reason to prevent these filters from applying to pages?

This is my position as well. The problem is the way they were running in earlier previews is over the RequestDelegate (i.e. Func<HttpContext, Task> for the Endpoints create for razor pages, and did not provide full fidelity MethodInfos or invocation contexts the way other MVC filters do.

The same is true right now for MVC actions (until after this change merged after which those too will be skipped). @davidfowl opened a draft PR (#42557) to run these filters the way our customers expect for MVC actions. I'm @captainsafia is going to take this over since he's on vacation.

We wanted to include razor pages in this PR as well, but the problem is that razor pages can effectively have multiple MethodInfos per endpoint, and that doesn't fit well with our new filter abstraction. We hope to resolve this issue and run filters razor pages in a future release, but we don't know that we can do that in time for .NET 7. We've been considering whether we can "light up" filters for razor pages in future releases without breaking apps.

- Also add MethodInfo to all endpoint metadata in RouteEndpointDataSource
@halter73 halter73 requested a review from Tratcher as a code owner July 29, 2022 23:13
@halter73
Copy link
Member Author

halter73 commented Jul 29, 2022

I updated this PR to do the renames suggested in #43000 and #42592. I assigned both of these to myself.

I also reacted to @davidfowl's and @captainsafia's feedback about adding the MethodInfo to the endpoint metadata for old-fashioned RequestDelegate-defined endpoints. This will make it show up both with in the .WithOpenApi() output and the ApiExplorer stuff we shipped in .NET 6 used by things like swashbuckle and nswag.

Are we sure want this to affect ApiExplorer too? I like that this keeps things consistent with .WithOpenApi() but we'll certainly want to make a breaking change announcement.

@halter73
Copy link
Member Author

halter73 commented Jul 29, 2022

Are we sure want this to affect ApiExplorer too?

Even if we do agree this is the direction we should take, I think we need an easy way to opt out of this globally for people who might not want this behavior but want to easily upgrade their existing apps using something like swashbuckle or nswag to .NET 7.

Applications might call into libraries that call MapXXX internally making adding metadata to these endpoints to the description might be tricky. Doing something like changing app.MapLibraryEndpoints() to app.MapGroup("").ExcludeFromDescription().MapLibraryEndpoints() might work. If .MapLibraryEndpoints() already returns an IEndpointConventionBuilder, you wouldn't even need the group with an empty prefix.

We might want to reopen #34068 and add an IgnoreApi() extension method that works for both ApiExplorer and WithOpenApi(). @martincostello

Edit: Updated to reflect ExcludeFromDescription() exists and is respected by both ApiExplorer and WithOpenApi. I knew we must have something.

@halter73
Copy link
Member Author

halter73 commented Aug 3, 2022

I think I've addressed all the PR feedback.

I undid the renames to reduce merge conflicts in #42557. The renames weren't the point of this PR. I thought I was saving work, but I wasn't. We also want to expose the EndopintBuilder in more places (see #43000 (comment)). This will be done in another PR.

This reverts commit bb2b157.
- No. I do not think normalizing the display names is a breaking change.
@halter73 halter73 enabled auto-merge (squash) August 6, 2022 00:18
@halter73 halter73 merged commit 5eb02a4 into main Aug 6, 2022
@halter73 halter73 deleted the halter73/42703 branch August 6, 2022 02:06
@ghost ghost added this to the 7.0-rc1 milestone Aug 6, 2022
@halter73 halter73 restored the halter73/42703 branch August 12, 2022 22:59
@halter73 halter73 deleted the halter73/42703 branch August 12, 2022 22:59
@amcasey amcasey added area-middleware Includes: URL rewrite, redirect, response cache/compression, session, and other general middlewares and removed area-runtime labels Jun 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-middleware Includes: URL rewrite, redirect, response cache/compression, session, and other general middlewares
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove RequestDelegateFactory call from RouteEndpointBuilder
7 participants