diff --git a/src/Umbraco.Web.Common/Routing/RoutableDocumentFilter.cs b/src/Umbraco.Web.Common/Routing/RoutableDocumentFilter.cs index 8a928af72d..f3f9c9b814 100644 --- a/src/Umbraco.Web.Common/Routing/RoutableDocumentFilter.cs +++ b/src/Umbraco.Web.Common/Routing/RoutableDocumentFilter.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Common.Routing /// public sealed class RoutableDocumentFilter { - private readonly ConcurrentDictionary _routeChecks = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _routeChecks = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly EndpointDataSource _endpointDataSource; @@ -143,6 +143,11 @@ namespace Umbraco.Web.Common.Routing return true; } + // TODO: We have a problem here: + // For every page that is rendered we are storing the URL and if it's routable in _routeChecks which + // is a small memory leak. Not sure how we work around this since routes are all dynamic and we don't want + // to double route everything on each request. Maybe instead of a growing list it's a list with a max capacity? + // check if the current request matches a route, if so then it is reserved. var hasRoute = _routeChecks.GetOrAdd(absPath, x => MatchesEndpoint(absPath)); if (hasRoute) @@ -168,13 +173,20 @@ namespace Umbraco.Web.Common.Routing private bool MatchesEndpoint(string absPath) { - // Borrowed from https://stackoverflow.com/a/59550580 + // Borrowed and modified from https://stackoverflow.com/a/59550580 // Return a collection of Microsoft.AspNetCore.Http.Endpoint instances. - IEnumerable routeEndpoints = _endpointDataSource?.Endpoints.Cast(); - var routeValues = new RouteValueDictionary(); + IEnumerable routeEndpoints = _endpointDataSource?.Endpoints + .OfType() + .Where(x => + { + // We don't want to include dynamic endpoints in this check since we would have no idea if that + // matches since they will probably match everything. + bool isDynamic = x.Metadata.OfType().Any(x => x.IsDynamic); + return !isDynamic; + }); - // string localPath = new Uri(absPath).LocalPath; + var routeValues = new RouteValueDictionary(); // To get the matchedEndpoint of the provide url RouteEndpoint matchedEndpoint = routeEndpoints diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs index 32b11bf876..5d0c564df3 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs @@ -34,6 +34,7 @@ namespace Umbraco.Web.Website.Routing private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeState _runtime; private readonly IUmbracoRouteValuesFactory _routeValuesFactory; + private readonly RoutableDocumentFilter _routableDocumentFilter; /// /// Initializes a new instance of the class. @@ -45,7 +46,8 @@ namespace Umbraco.Web.Website.Routing IOptions globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtime, - IUmbracoRouteValuesFactory routeValuesFactory) + IUmbracoRouteValuesFactory routeValuesFactory, + RoutableDocumentFilter routableDocumentFilter) { _logger = logger; _umbracoContextAccessor = umbracoContextAccessor; @@ -54,6 +56,7 @@ namespace Umbraco.Web.Website.Routing _hostingEnvironment = hostingEnvironment; _runtime = runtime; _routeValuesFactory = routeValuesFactory; + _routableDocumentFilter = routableDocumentFilter; } /// @@ -71,6 +74,11 @@ namespace Umbraco.Web.Website.Routing return values; } + if (!_routableDocumentFilter.IsDocumentRequest(httpContext.Request.Path)) + { + return values; + } + // Check if there is no existing content and return the no content controller if (!_umbracoContextAccessor.UmbracoContext.Content.HasContent()) {