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; + } } } diff --git a/src/Umbraco.Web/UrlHelperRenderExtensions.cs b/src/Umbraco.Web/UrlHelperRenderExtensions.cs index d1eb46a2b8..70a414ff29 100644 --- a/src/Umbraco.Web/UrlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/UrlHelperRenderExtensions.cs @@ -261,52 +261,52 @@ namespace Umbraco.Web // // #endregion - /// - /// 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 UrlHelper url, string action, string controllerName) - { - return url.SurfaceAction(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 UrlHelper url, string action, string controllerName, object additionalRouteVals) - { - return url.SurfaceAction(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 UrlHelper url, 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 = CreateEncryptedRouteString(controllerName, action, area, additionalRouteVals); - - var result = Current.UmbracoContext.OriginalRequestUrl.AbsolutePath.EnsureEndsWith('?') + "ufprt=" + encryptedRoute; - return result; - } + // /// + // /// 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 UrlHelper url, string action, string controllerName) + // { + // return url.SurfaceAction(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 UrlHelper url, string action, string controllerName, object additionalRouteVals) + // { + // return url.SurfaceAction(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 UrlHelper url, 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 = CreateEncryptedRouteString(controllerName, action, area, additionalRouteVals); + // + // var result = Current.UmbracoContext.OriginalRequestUrl.AbsolutePath.EnsureEndsWith('?') + "ufprt=" + encryptedRoute; + // return result; + // } //TODO Move to LinkGenerator // /// @@ -384,42 +384,42 @@ namespace Umbraco.Web // return url.SurfaceAction(action, typeof (T), additionalRouteVals); // } - /// - /// This is used in methods like BeginUmbracoForm and SurfaceAction to generate an encrypted string which gets submitted in a request for which - /// Umbraco can decrypt during the routing process in order to delegate the request to a specific MVC Controller. - /// - /// - /// - /// - /// - /// - internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null) - { - if (controllerName == null) throw new ArgumentNullException(nameof(controllerName)); - if (string.IsNullOrEmpty(controllerName)) throw new ArgumentException("Value can't be empty.", nameof(controllerName)); - if (controllerAction == null) throw new ArgumentNullException(nameof(controllerAction)); - if (string.IsNullOrEmpty(controllerAction)) throw new ArgumentException("Value can't be empty.", nameof(controllerAction)); - if (area == null) throw new ArgumentNullException(nameof(area)); - - //need to create a params string as Base64 to put into our hidden field to use during the routes - var surfaceRouteParams = $"c={HttpUtility.UrlEncode(controllerName)}&a={HttpUtility.UrlEncode(controllerAction)}&ar={area}"; - - //checking if the additional route values is already a dictionary and convert to querystring - string additionalRouteValsAsQuery; - if (additionalRouteVals != null) - { - if (additionalRouteVals is Dictionary additionalRouteValsAsDictionary) - additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); - else - additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); - } - else - additionalRouteValsAsQuery = null; - - if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false) - surfaceRouteParams += "&" + additionalRouteValsAsQuery; - - return surfaceRouteParams.EncryptWithMachineKey(); - } + // /// + // /// This is used in methods like BeginUmbracoForm and SurfaceAction to generate an encrypted string which gets submitted in a request for which + // /// Umbraco can decrypt during the routing process in order to delegate the request to a specific MVC Controller. + // /// + // /// + // /// + // /// + // /// + // /// + // internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null) + // { + // if (controllerName == null) throw new ArgumentNullException(nameof(controllerName)); + // if (string.IsNullOrEmpty(controllerName)) throw new ArgumentException("Value can't be empty.", nameof(controllerName)); + // if (controllerAction == null) throw new ArgumentNullException(nameof(controllerAction)); + // if (string.IsNullOrEmpty(controllerAction)) throw new ArgumentException("Value can't be empty.", nameof(controllerAction)); + // if (area == null) throw new ArgumentNullException(nameof(area)); + // + // //need to create a params string as Base64 to put into our hidden field to use during the routes + // var surfaceRouteParams = $"c={HttpUtility.UrlEncode(controllerName)}&a={HttpUtility.UrlEncode(controllerAction)}&ar={area}"; + // + // //checking if the additional route values is already a dictionary and convert to querystring + // string additionalRouteValsAsQuery; + // if (additionalRouteVals != null) + // { + // if (additionalRouteVals is Dictionary additionalRouteValsAsDictionary) + // additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); + // else + // additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); + // } + // else + // additionalRouteValsAsQuery = null; + // + // if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false) + // surfaceRouteParams += "&" + additionalRouteValsAsQuery; + // + // return surfaceRouteParams.EncryptWithMachineKey(); + // } } }