-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Add ability to modify UseRouting/UseEndpoint behavior for WebApplicationBuilder #35336
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
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2cb5b13
WIP
BrennanConroy 532be58
more WIP
BrennanConroy 4a60dbb
more
BrennanConroy 5dffb3d
lets do this
BrennanConroy 856d8a8
fb
BrennanConroy 0cc8fd5
some stuff
BrennanConroy 752f303
progress
BrennanConroy 9edd5eb
remove key
BrennanConroy 03af810
remove prop
BrennanConroy 925682c
fix
BrennanConroy 67f0ba4
fin
BrennanConroy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ | |
using System.Diagnostics; | ||
using System.Reflection; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.Routing; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
|
@@ -17,11 +16,10 @@ namespace Microsoft.AspNetCore.Builder | |
/// </summary> | ||
public sealed class WebApplicationBuilder | ||
{ | ||
private const string EndpointRouteBuilderKey = "__EndpointRouteBuilder"; | ||
|
||
private readonly HostBuilder _hostBuilder = new(); | ||
private readonly BootstrapHostBuilder _bootstrapHostBuilder; | ||
private readonly WebApplicationServiceCollection _services = new(); | ||
private const string EndpointRouteBuilderKey = "__EndpointRouteBuilder"; | ||
|
||
private WebApplication? _builtApplication; | ||
|
||
|
@@ -187,48 +185,39 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui | |
{ | ||
Debug.Assert(_builtApplication is not null); | ||
|
||
// UseRouting called before WebApplication such as in a StartupFilter | ||
// lets remove the property and reset it at the end so we don't mess with the routes in the filter | ||
if (app.Properties.TryGetValue(EndpointRouteBuilderKey, out var priorRouteBuilder)) | ||
{ | ||
app.Properties.Remove(EndpointRouteBuilderKey); | ||
} | ||
|
||
if (context.HostingEnvironment.IsDevelopment()) | ||
{ | ||
// TODO: add test for this | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't have coverage for this? File an issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
app.UseDeveloperExceptionPage(); | ||
} | ||
|
||
var implicitRouting = false; | ||
// Wrap the entire destination pipeline in UseRouting() and UseEndpoints(), essentially: | ||
// destination.UseRouting() | ||
// destination.Run(source) | ||
// destination.UseEndpoints() | ||
|
||
// Set the route builder so that UseRouting will use the WebApplication as the IEndpointRouteBuilder for route matching | ||
app.Properties.Add(WebApplication.GlobalEndpointRouteBuilderKey, _builtApplication); | ||
|
||
// The endpoints were already added on the outside | ||
// Only call UseRouting() if there are endpoints configured and UseRouting() wasn't called on the global route builder already | ||
if (_builtApplication.DataSources.Count > 0) | ||
{ | ||
// The user did not register the routing middleware so wrap the entire | ||
// destination pipeline in UseRouting() and UseEndpoints(), essentially: | ||
// destination.UseRouting() | ||
// destination.Run(source) | ||
// destination.UseEndpoints() | ||
|
||
// Copy endpoints to the IEndpointRouteBuilder created by an explicit call to UseRouting() if possible. | ||
var targetRouteBuilder = GetEndpointRouteBuilder(_builtApplication); | ||
|
||
if (targetRouteBuilder is null) | ||
// If this is set, someone called UseRouting() when a global route builder was already set | ||
if (!_builtApplication.Properties.TryGetValue(EndpointRouteBuilderKey, out var localRouteBuilder)) | ||
{ | ||
// The app defined endpoints without calling UseRouting() explicitly, so call UseRouting() implicitly. | ||
app.UseRouting(); | ||
|
||
// An implicitly created IEndpointRouteBuilder was addeded to app.Properties by the UseRouting() call above. | ||
targetRouteBuilder = GetEndpointRouteBuilder(app)!; | ||
implicitRouting = true; | ||
} | ||
|
||
// Copy the endpoints to the explicitly or implicitly created IEndopintRouteBuilder. | ||
foreach (var ds in _builtApplication.DataSources) | ||
else | ||
{ | ||
targetRouteBuilder.DataSources.Add(ds); | ||
} | ||
|
||
// UseEndpoints consumes the DataSources immediately to populate CompositeEndpointDataSource via RouteOptions, | ||
// so it must be called after we copy the endpoints. | ||
if (!implicitRouting) | ||
{ | ||
// UseRouting() was called explicitely, but we may still need to call UseEndpoints() implicitely at | ||
// the end of the pipeline. | ||
_builtApplication.UseEndpoints(_ => { }); | ||
// UseEndpoints will be looking for the RouteBuilder so make sure it's set | ||
app.Properties[EndpointRouteBuilderKey] = localRouteBuilder; | ||
} | ||
} | ||
|
||
|
@@ -239,11 +228,9 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui | |
return _builtApplication.BuildRequestDelegate(); | ||
}); | ||
|
||
// Implicitly call UseEndpoints() at the end of the pipeline if UseRouting() was called implicitly. | ||
// We could add this to the end of _buildApplication instead if UseEndpoints() was not so picky about | ||
// being called with the same IApplicationBluilder instance as UseRouting(). | ||
if (implicitRouting) | ||
if (_builtApplication.DataSources.Count > 0) | ||
{ | ||
// We don't know if user code called UseEndpoints(), so we will call it just in case, UseEndpoints() will ignore duplicate DataSources | ||
app.UseEndpoints(_ => { }); | ||
} | ||
|
||
|
@@ -252,12 +239,15 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui | |
{ | ||
app.Properties[item.Key] = item.Value; | ||
} | ||
} | ||
|
||
private static IEndpointRouteBuilder? GetEndpointRouteBuilder(IApplicationBuilder app) | ||
{ | ||
app.Properties.TryGetValue(EndpointRouteBuilderKey, out var value); | ||
return (IEndpointRouteBuilder?)value; | ||
// Remove the route builder to clean up the properties, we're done adding routes to the pipeline | ||
app.Properties.Remove(WebApplication.GlobalEndpointRouteBuilderKey); | ||
|
||
// reset route builder if it existed, this is needed for StartupFilters | ||
if (priorRouteBuilder is not null) | ||
{ | ||
app.Properties[EndpointRouteBuilderKey] = priorRouteBuilder; | ||
} | ||
} | ||
|
||
private class LoggingBuilder : ILoggingBuilder | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.