diff --git a/src/Umbraco.Web.Common/Extensions/FriendlyUrlHelperExtensions.cs b/src/Umbraco.Web.Common/Extensions/FriendlyUrlHelperExtensions.cs new file mode 100644 index 0000000000..0340ce7a50 --- /dev/null +++ b/src/Umbraco.Web.Common/Extensions/FriendlyUrlHelperExtensions.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.Web; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Extensions +{ + public static class FriendlyUrlHelperExtensions + { + + private static IUmbracoContext UmbracoContext { get; } = + StaticServiceProvider.Instance.GetRequiredService().GetRequiredUmbracoContext(); + + private static IDataProtectionProvider DataProtectionProvider { get; } = + StaticServiceProvider.Instance.GetRequiredService(); + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, string action, string controllerName) + => UrlHelperExtensions.SurfaceAction(url, UmbracoContext, DataProtectionProvider, action, controllerName); + + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, string action, string controllerName, object additionalRouteVals) + => UrlHelperExtensions.SurfaceAction(url, UmbracoContext, DataProtectionProvider, action, controllerName, additionalRouteVals); + + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, string action, string controllerName, string area, object additionalRouteVals) + => UrlHelperExtensions.SurfaceAction(url, UmbracoContext, DataProtectionProvider, action, controllerName, area, additionalRouteVals); + } +} diff --git a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs index d3fd3bddba..fb2a272585 100644 --- a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Web; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; @@ -12,8 +14,10 @@ using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PropertyEditors.ValueConverters; +using Umbraco.Cms.Core.Web; using Umbraco.Cms.Core.WebAssets; using Umbraco.Cms.Web.Common.Controllers; +using Umbraco.Cms.Web.Common.Security; namespace Umbraco.Extensions { @@ -280,5 +284,51 @@ namespace Umbraco.Extensions return htmlEncode ? new HtmlString(HttpUtility.HtmlEncode(url)) : new HtmlString(url); } + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, IUmbracoContext umbracoContext, IDataProtectionProvider dataProtectionProvider,string action, string controllerName) + { + return url.SurfaceAction(umbracoContext, dataProtectionProvider, action, controllerName, null); + } + + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, IUmbracoContext umbracoContext, IDataProtectionProvider dataProtectionProvider,string action, string controllerName, object additionalRouteVals) + { + return url.SurfaceAction(umbracoContext, dataProtectionProvider, action, controllerName, "", additionalRouteVals); + } + + /// + /// Generates a URL based on the current Umbraco URL with a custom query string that will route to the specified SurfaceController + /// + /// + /// + /// + /// + /// + /// + public static string SurfaceAction(this IUrlHelper url, IUmbracoContext umbracoContext, IDataProtectionProvider dataProtectionProvider, string action, string controllerName, string area, object additionalRouteVals) + { + if (action == null) throw new ArgumentNullException(nameof(action)); + if (string.IsNullOrEmpty(action)) throw new ArgumentException("Value can't be empty.", nameof(action)); + if (controllerName == null) throw new ArgumentNullException(nameof(controllerName)); + if (string.IsNullOrEmpty(controllerName)) throw new ArgumentException("Value can't be empty.", nameof(controllerName)); + + var encryptedRoute = EncryptionHelper.CreateEncryptedRouteString(dataProtectionProvider, controllerName, action, area, additionalRouteVals); + + var result = umbracoContext.OriginalRequestUrl.AbsolutePath.EnsureEndsWith('?') + "ufprt=" + encryptedRoute; + return result; + } } }