diff --git a/src/Umbraco.Web.Common/Extensions/EndpointDataSourceExtensions.cs b/src/Umbraco.Web.Common/Extensions/EndpointDataSourceExtensions.cs
new file mode 100644
index 0000000000..f1d66a25c5
--- /dev/null
+++ b/src/Umbraco.Web.Common/Extensions/EndpointDataSourceExtensions.cs
@@ -0,0 +1,35 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+
+namespace Umbraco.Cms.Web.Common.Extensions;
+
+///
+/// Extensions methods for EndpointDataSource.
+///
+public static class EndpointDataSourceExtensions
+{
+ ///
+ /// Gets an endpoint that matches the specified path.
+ ///
+ /// The end point data source.
+ /// The link parsers using to parse the path.
+ /// The path to be parsed.
+ /// The mathcing route values for the mathcing endpoint.
+ /// The endpoint or null if not found.
+ public static Endpoint? GetEndpointByPath(this EndpointDataSource endpointDatasource, LinkParser linkParser, PathString path, out RouteValueDictionary? routeValues)
+ {
+ routeValues = null;
+
+ foreach (Endpoint endpoint in endpointDatasource.Endpoints)
+ {
+ routeValues = linkParser.ParsePathByEndpoint(endpoint, path);
+
+ if (routeValues != null)
+ {
+ return endpoint;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/Umbraco.Web.Common/Extensions/EndpointExtensions.cs b/src/Umbraco.Web.Common/Extensions/EndpointExtensions.cs
new file mode 100644
index 0000000000..684c2e4c3f
--- /dev/null
+++ b/src/Umbraco.Web.Common/Extensions/EndpointExtensions.cs
@@ -0,0 +1,41 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Routing;
+
+namespace Umbraco.Cms.Web.Common.Extensions;
+
+///
+/// Extensions methods for Endpoint.
+///
+public static class EndpointExtensions
+{
+ ///
+ /// Gets the controller action descriptor from the endpoint.
+ ///
+ /// The endpoint.
+ /// The controller action descriptor or null if not found.
+ public static ControllerActionDescriptor? GetControllerActionDescriptor(this Endpoint endpoint)
+ {
+ return endpoint.Metadata.GetMetadata();
+ }
+
+ ///
+ /// Gets the route name metadata from the endpoint.
+ ///
+ /// The endpoint.
+ /// The route name metadata or null if not found.
+ public static RouteNameMetadata? GetRouteNameMetadata(this Endpoint endpoint)
+ {
+ return endpoint.Metadata.GetMetadata();
+ }
+
+ ///
+ /// Gets the route name from the endpoint metadata.
+ ///
+ /// The endpoint.
+ /// The route name or null if not found.
+ public static string? GetRouteName(this Endpoint endpoint)
+ {
+ return endpoint.GetRouteNameMetadata()?.RouteName;
+ }
+}
diff --git a/src/Umbraco.Web.Common/Extensions/LinkParserExtensions.cs b/src/Umbraco.Web.Common/Extensions/LinkParserExtensions.cs
new file mode 100644
index 0000000000..8cb9156103
--- /dev/null
+++ b/src/Umbraco.Web.Common/Extensions/LinkParserExtensions.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+
+namespace Umbraco.Cms.Web.Common.Extensions;
+
+///
+/// Extension methods for LinkParser.
+///
+public static class LinkParserExtensions
+{
+ ///
+ /// Parses the path using the specified endpoint and returns the route values if a the path matches the route pattern.
+ ///
+ /// The link parser.
+ /// The endpoint.
+ /// The path to parse.
+ /// The route values if the path matches or null.
+ public static RouteValueDictionary? ParsePathByEndpoint(this LinkParser linkParser, Endpoint endpoint, PathString path)
+ {
+ var name = endpoint.GetRouteName();
+
+ if (name != null)
+ {
+ return linkParser.ParsePathByEndpointName(name, path);
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
diff --git a/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs b/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs
index 7b1b9960e3..707dfe0b8d 100644
--- a/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs
+++ b/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs
@@ -1,11 +1,9 @@
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
-using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Web.Common.Controllers;
using Umbraco.Cms.Web.Common.Routing;
@@ -21,23 +19,42 @@ public class UmbracoVirtualPageFilterAttribute : Attribute, IAsyncActionFilter
///
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
- Endpoint? endpoint = context.HttpContext.GetEndpoint();
+ // Check if there's proxied ViewData (i.e. returned from a SurfaceController)
+ // We don't want to find the content and set route values again if this is from a surface controller
+ ProxyViewDataFeature? proxyViewDataFeature = context.HttpContext.Features.Get();
- // Check if there is any delegate in the metadata of the route, this
- // will occur when using the ForUmbraco method during routing.
- CustomRouteContentFinderDelegate? contentFinder =
- endpoint?.Metadata.OfType().FirstOrDefault();
-
- if (contentFinder != null)
+ if (proxyViewDataFeature != null)
{
- await SetUmbracoRouteValues(context, contentFinder.FindContent(context));
+ if (context.Controller is Controller controller)
+ {
+ foreach (KeyValuePair kv in proxyViewDataFeature.ViewData)
+ {
+ controller.ViewData[kv.Key] = kv.Value;
+ }
+ }
}
else
{
- // Check if the controller is IVirtualPageController and then use that to FindContent
- if (context.Controller is IVirtualPageController ctrl)
+ Endpoint? endpoint = context.HttpContext.GetEndpoint();
+
+ if (endpoint != null)
{
- await SetUmbracoRouteValues(context, ctrl.FindContent(context));
+ IUmbracoVirtualPageRoute umbracoVirtualPageRoute = context.HttpContext.RequestServices.GetRequiredService();
+
+ IPublishedContent? publishedContent = umbracoVirtualPageRoute.FindContent(endpoint, context);
+
+ if (publishedContent != null)
+ {
+ await umbracoVirtualPageRoute.SetRouteValues(
+ context.HttpContext,
+ publishedContent,
+ (ControllerActionDescriptor)context.ActionDescriptor);
+ }
+ else
+ {
+ // if there is no content then it should be a not found
+ context.Result = new NotFoundResult();
+ }
}
}
@@ -47,32 +64,4 @@ public class UmbracoVirtualPageFilterAttribute : Attribute, IAsyncActionFilter
await next();
}
}
-
- private async Task SetUmbracoRouteValues(ActionExecutingContext context, IPublishedContent? content)
- {
- if (content != null)
- {
- UriUtility uriUtility = context.HttpContext.RequestServices.GetRequiredService();
-
- var originalRequestUrl = new Uri(context.HttpContext.Request.GetEncodedUrl());
- Uri cleanedUrl = uriUtility.UriToUmbraco(originalRequestUrl);
-
- IPublishedRouter router = context.HttpContext.RequestServices.GetRequiredService();
-
- IPublishedRequestBuilder requestBuilder = await router.CreateRequestAsync(cleanedUrl);
- requestBuilder.SetPublishedContent(content);
- IPublishedRequest publishedRequest = requestBuilder.Build();
-
- var routeValues = new UmbracoRouteValues(
- publishedRequest,
- (ControllerActionDescriptor)context.ActionDescriptor);
-
- context.HttpContext.Features.Set(routeValues);
- }
- else
- {
- // if there is no content then it should be a not found
- context.Result = new NotFoundResult();
- }
- }
}
diff --git a/src/Umbraco.Web.Common/Routing/IUmbracoVirtualPageRoute.cs b/src/Umbraco.Web.Common/Routing/IUmbracoVirtualPageRoute.cs
new file mode 100644
index 0000000000..dc8453eb62
--- /dev/null
+++ b/src/Umbraco.Web.Common/Routing/IUmbracoVirtualPageRoute.cs
@@ -0,0 +1,64 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Routing;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Routing;
+
+namespace Umbraco.Cms.Web.Common.Routing;
+
+///
+/// This is used to setup the virtual page route so the route values and content are set for virtual pages.
+///
+public interface IUmbracoVirtualPageRoute
+{
+ ///
+ /// This sets up the virtual page route for the current request if a mtahcing endpoint is found.
+ ///
+ /// The HTTP context.
+ /// Nothing
+ Task SetupVirtualPageRoute(HttpContext httpContext);
+
+ ///
+ /// Finds the content from the custom route finder delegate or the virtual page controller.
+ /// Note - This creates a dummay action executing context so the FindContent method of the
+ /// IVirtualPageController can be called (without changing the interface contract).
+ ///
+ /// The endpoint.
+ /// The HTTP context.
+ /// The route values.
+ /// The action descriptor.
+ /// The controller.
+ ///
+ IPublishedContent? FindContent(
+ Endpoint endpoint,
+ HttpContext httpContext,
+ RouteValueDictionary routeValues,
+ ControllerActionDescriptor controllerActionDescriptor,
+ object controller);
+
+ ///
+ /// Finds the content from the custom route finder delegate or the virtual page controller.
+ ///
+ /// The endpoint.
+ /// The action executing context.
+ /// The published content if found or null.
+ IPublishedContent? FindContent(Endpoint endpoint, ActionExecutingContext actionExecutingContext);
+
+ ///
+ /// Creates the published request for the published content.
+ ///
+ /// The HTTP context.
+ /// The published content.
+ /// The published request.
+ Task CreatePublishedRequest(HttpContext httpContext, IPublishedContent publishedContent);
+
+ ///
+ /// Sets the route values for the published content and the controller action descriptor.
+ ///
+ /// The HTTP context.
+ /// The published content.
+ /// The controller action descriptor.
+ /// Nothing.
+ Task SetRouteValues(HttpContext httpContext, IPublishedContent publishedContent, ControllerActionDescriptor controllerActionDescriptor);
+}
diff --git a/src/Umbraco.Web.Common/Routing/UmbracoVirtualPageRoute.cs b/src/Umbraco.Web.Common/Routing/UmbracoVirtualPageRoute.cs
new file mode 100644
index 0000000000..f0d0427438
--- /dev/null
+++ b/src/Umbraco.Web.Common/Routing/UmbracoVirtualPageRoute.cs
@@ -0,0 +1,178 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Routing;
+using Umbraco.Cms.Web.Common.Controllers;
+using Umbraco.Cms.Web.Common.Extensions;
+
+namespace Umbraco.Cms.Web.Common.Routing;
+
+///
+/// This is used to setup the virtual page route so the route values and content are set for virtual pages.
+///
+public class UmbracoVirtualPageRoute : IUmbracoVirtualPageRoute
+{
+ private readonly EndpointDataSource _endpointDataSource;
+ private readonly LinkParser _linkParser;
+ private readonly UriUtility _uriUtility;
+ private readonly IPublishedRouter _publishedRouter;
+
+ ///
+ /// Constructor.
+ ///
+ /// The endpoint data source.
+ /// The link parser.
+ /// The Uri utility.
+ /// The published router.
+ public UmbracoVirtualPageRoute(
+ EndpointDataSource endpointDataSource,
+ LinkParser linkParser,
+ UriUtility uriUtility,
+ IPublishedRouter publishedRouter)
+ {
+ _endpointDataSource = endpointDataSource;
+ _linkParser = linkParser;
+ _uriUtility = uriUtility;
+ _publishedRouter = publishedRouter;
+ }
+
+ ///
+ /// This sets up the virtual page route for the current request if a mtahcing endpoint is found.
+ ///
+ /// The HTTP context.
+ /// Nothing
+ public async Task SetupVirtualPageRoute(HttpContext httpContext)
+ {
+ // Try and find an endpoint for the current path...
+ Endpoint? endpoint = _endpointDataSource.GetEndpointByPath(_linkParser, httpContext.Request.Path, out RouteValueDictionary? routeValues);
+
+ if (endpoint != null && routeValues != null)
+ {
+ ControllerActionDescriptor? controllerActionDescriptor = endpoint.GetControllerActionDescriptor();
+
+ if (controllerActionDescriptor != null)
+ {
+ Type controllerType = controllerActionDescriptor.ControllerTypeInfo.AsType();
+
+ if (controllerType != null)
+ {
+ // Get the controller for the endpoint
+ var controller = httpContext.RequestServices.GetRequiredService(controllerType);
+
+ // Try and find the content if this is a virtual page
+ IPublishedContent? publishedContent = FindContent(
+ endpoint,
+ httpContext,
+ routeValues,
+ controllerActionDescriptor,
+ controller);
+
+ if (publishedContent != null)
+ {
+ // If we have content then set the route values
+ await SetRouteValues(httpContext, publishedContent, controllerActionDescriptor);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Finds the content from the custom route finder delegate or the virtual page controller.
+ /// Note - This creates a dummay action executing context so the FindContent method of the
+ /// IVirtualPageController can be called (without changing the interface contract).
+ ///
+ /// The endpoint.
+ /// The HTTP context.
+ /// The route values.
+ /// The action descriptor.
+ /// The controller.
+ ///
+ public IPublishedContent? FindContent(
+ Endpoint endpoint,
+ HttpContext httpContext,
+ RouteValueDictionary routeValues,
+ ControllerActionDescriptor controllerActionDescriptor,
+ object controller)
+ {
+ var actionExecutingContext = new ActionExecutingContext(
+ new ActionContext(
+ httpContext,
+ new RouteData(routeValues),
+ controllerActionDescriptor),
+ filters: new List(),
+ actionArguments: new Dictionary(),
+ controller: controller);
+
+ return FindContent(endpoint, actionExecutingContext);
+ }
+
+ ///
+ /// Finds the content from the custom route finder delegate or the virtual page controller.
+ ///
+ /// The endpoint.
+ /// The action executing context.
+ /// The published content if found or null.
+ public IPublishedContent? FindContent(Endpoint endpoint, ActionExecutingContext actionExecutingContext)
+ {
+ // Check if there is any delegate in the metadata of the route, this
+ // will occur when using the ForUmbraco method during routing.
+ CustomRouteContentFinderDelegate? contentFinder =
+ endpoint?.Metadata.OfType().FirstOrDefault();
+
+ if (contentFinder != null)
+ {
+ return contentFinder.FindContent(actionExecutingContext);
+ }
+ else
+ {
+ // Check if the controller is IVirtualPageController and then use that to FindContent
+ if (actionExecutingContext.Controller is IVirtualPageController virtualPageController)
+ {
+ return virtualPageController.FindContent(actionExecutingContext);
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Creates the published request for the published content.
+ ///
+ /// The HTTP context.
+ /// The published content.
+ /// The published request.
+ public async Task CreatePublishedRequest(HttpContext httpContext, IPublishedContent publishedContent)
+ {
+ var originalRequestUrl = new Uri(httpContext.Request.GetEncodedUrl());
+ Uri cleanedUrl = _uriUtility.UriToUmbraco(originalRequestUrl);
+
+ IPublishedRequestBuilder requestBuilder = await _publishedRouter.CreateRequestAsync(cleanedUrl);
+ requestBuilder.SetPublishedContent(publishedContent);
+
+ return requestBuilder.Build();
+ }
+
+ ///
+ /// Sets the route values for the published content and the controller action descriptor.
+ ///
+ /// The HTTP context.
+ /// The published content.
+ /// The controller action descriptor.
+ /// Nothing.
+ public async Task SetRouteValues(HttpContext httpContext, IPublishedContent publishedContent, ControllerActionDescriptor controllerActionDescriptor)
+ {
+ IPublishedRequest publishedRequest = await CreatePublishedRequest(httpContext, publishedContent);
+
+ var umbracoRouteValues = new UmbracoRouteValues(
+ publishedRequest,
+ controllerActionDescriptor);
+
+ httpContext.Features.Set(umbracoRouteValues);
+ }
+}
diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
index 5260006768..1bd05a424d 100644
--- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -1,9 +1,14 @@
+using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.DependencyInjection;
+using Umbraco.Cms.Core.Routing;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.DependencyInjection;
using Umbraco.Cms.Web.Common.Middleware;
using Umbraco.Cms.Web.Common.Routing;
@@ -40,9 +45,21 @@ public static partial class UmbracoBuilderExtensions
builder.Services.AddDataProtection();
builder.Services.AddAntiforgery();
- builder.Services.AddSingleton();
+ builder.Services.AddSingleton(x => new UmbracoRouteValueTransformer(
+ x.GetRequiredService>(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService(),
+ x.GetRequiredService()
+ ));
builder.Services.AddSingleton();
builder.Services.TryAddEnumerable(Singleton());
+ builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs
index d4394d2e2a..c1cc360500 100644
--- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs
+++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
@@ -13,6 +14,7 @@ using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
+using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Cms.Web.Common.Routing;
using Umbraco.Cms.Web.Common.Security;
using Umbraco.Cms.Web.Website.Controllers;
@@ -46,8 +48,9 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
private readonly IUmbracoRouteValuesFactory _routeValuesFactory;
private readonly IRuntimeState _runtime;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
+ private readonly IUmbracoVirtualPageRoute _umbracoVirtualPageRoute;
- [Obsolete("Please use constructor that does not take IOptions, IHostingEnvironment & IEventAggregator instead")]
+ [Obsolete("Please use constructor that is not obsolete, instead of this. This will be removed in Umbraco 13.")]
public UmbracoRouteValueTransformer(
ILogger logger,
IUmbracoContextAccessor umbracoContextAccessor,
@@ -61,10 +64,26 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
IControllerActionSearcher controllerActionSearcher,
IEventAggregator eventAggregator,
IPublicAccessRequestHandler publicAccessRequestHandler)
- : this(logger, umbracoContextAccessor, publishedRouter, runtime, routeValuesFactory, routableDocumentFilter, dataProtectionProvider, controllerActionSearcher, publicAccessRequestHandler)
+ : this(logger, umbracoContextAccessor, publishedRouter, runtime, routeValuesFactory, routableDocumentFilter, dataProtectionProvider, controllerActionSearcher, publicAccessRequestHandler, StaticServiceProvider.Instance.GetRequiredService())
{
}
+ [Obsolete("Please use constructor that is not obsolete, instead of this. This will be removed in Umbraco 13.")]
+ public UmbracoRouteValueTransformer(
+ ILogger logger,
+ IUmbracoContextAccessor umbracoContextAccessor,
+ IPublishedRouter publishedRouter,
+ IRuntimeState runtime,
+ IUmbracoRouteValuesFactory routeValuesFactory,
+ IRoutableDocumentFilter routableDocumentFilter,
+ IDataProtectionProvider dataProtectionProvider,
+ IControllerActionSearcher controllerActionSearcher,
+ IPublicAccessRequestHandler publicAccessRequestHandler)
+ : this(logger, umbracoContextAccessor, publishedRouter, runtime, routeValuesFactory, routableDocumentFilter, dataProtectionProvider, controllerActionSearcher, publicAccessRequestHandler, StaticServiceProvider.Instance.GetRequiredService())
+ {
+ }
+
+
///
/// Initializes a new instance of the class.
///
@@ -77,7 +96,8 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
IRoutableDocumentFilter routableDocumentFilter,
IDataProtectionProvider dataProtectionProvider,
IControllerActionSearcher controllerActionSearcher,
- IPublicAccessRequestHandler publicAccessRequestHandler)
+ IPublicAccessRequestHandler publicAccessRequestHandler,
+ IUmbracoVirtualPageRoute umbracoVirtualPageRoute)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_umbracoContextAccessor =
@@ -90,6 +110,7 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
_dataProtectionProvider = dataProtectionProvider;
_controllerActionSearcher = controllerActionSearcher;
_publicAccessRequestHandler = publicAccessRequestHandler;
+ _umbracoVirtualPageRoute = umbracoVirtualPageRoute;
}
///
@@ -147,6 +168,10 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
PostedDataProxyInfo? postedInfo = GetFormInfo(httpContext, values);
if (postedInfo != null)
{
+ // Ensure the virtual page content and route values are setup when submitting to a surface controller
+ // If we don't do this, the virtual page controller never gets called after the surface controller completes
+ await _umbracoVirtualPageRoute.SetupVirtualPageRoute(httpContext);
+
return HandlePostedValues(postedInfo, httpContext);
}
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs
index 3f98ca4bcb..cd48e870fc 100644
--- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs
@@ -21,6 +21,7 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
using Umbraco.Cms.Web.Common.Controllers;
+using Umbraco.Cms.Web.Common.Filters;
using Umbraco.Cms.Web.Common.Routing;
using Umbraco.Cms.Web.Website.Controllers;
using Umbraco.Cms.Web.Website.Routing;
@@ -53,20 +54,21 @@ public class UmbracoRouteValueTransformerTests
x.RewriteForPublishedContentAccessAsync(It.IsAny(), It.IsAny()))
.Returns((HttpContext ctx, UmbracoRouteValues routeVals) => Task.FromResult(routeVals));
+ var umbracoVirtualPageRoute = new Mock();
+ umbracoVirtualPageRoute.Setup(x => x.SetupVirtualPageRoute(It.IsAny()));
+
var transformer = new UmbracoRouteValueTransformer(
new NullLogger(),
ctx,
router ?? Mock.Of(),
- GetGlobalSettings(),
- TestHelper.GetHostingEnvironment(),
state,
routeValuesFactory ?? Mock.Of(),
filter ?? Mock.Of(x => x.IsDocumentRequest(It.IsAny()) == true),
Mock.Of(),
Mock.Of(),
- Mock.Of(),
- publicAccessRequestHandler.Object);
-
+ publicAccessRequestHandler.Object,
+ Mock.Of()
+ );
return transformer;
}