From 0c26a82489fd6e78ec6f95e3243f18f3c9a2d073 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 3 Feb 2021 15:47:27 +1100 Subject: [PATCH] Changes the umbraco route values to use http features intead of in route values which is much nicer, fixes the redirect to page result, tests a surface controller POST and it works, ensures the routing takes place before the form check, removes a bunch of old code --- src/Umbraco.Core/Constants-Web.cs | 2 - .../ModelBinders/ContentModelBinderTests.cs | 21 +- .../Controllers/SurfaceControllerTests.cs | 9 +- ...ts.cs => ControllerActionSearcherTests.cs} | 8 +- .../UmbracoRouteValueTransformerTests.cs | 26 +- .../Routing/UmbracoRouteValuesFactoryTests.cs | 10 +- .../PublishedRequestFilterAttribute.cs | 7 +- .../Controllers/RenderController.cs | 4 +- .../UmbracoPublishedContentCultureProvider.cs | 3 +- .../ModelBinders/ContentModelBinder.cs | 4 +- .../Security/EncryptionHelper.cs | 87 ++++-- .../ActionResults/UmbracoPageResult.cs | 21 +- .../Controllers/SurfaceController.cs | 29 +- .../UmbracoBuilderExtensions.cs | 2 +- .../Extensions/HtmlHelperRenderExtensions.cs | 15 +- ...ult.cs => ControllerActionSearchResult.cs} | 33 ++- ...aluator.cs => ControllerActionSearcher.cs} | 26 +- .../Routing/IControllerActionSearcher.cs | 7 + .../Routing/IUmbracoRouteValuesFactory.cs | 2 +- .../Routing/UmbracoRouteValueTransformer.cs | 147 +++++++-- .../Routing/UmbracoRouteValuesFactory.cs | 19 +- .../Mvc/RedirectToUmbracoPageResult.cs | 278 ------------------ .../Mvc/RedirectToUmbracoUrlResult.cs | 43 --- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 33 +-- src/Umbraco.Web/Mvc/SurfaceController.cs | 195 ------------ src/Umbraco.Web/Mvc/UmbracoPageResult.cs | 140 --------- .../Mvc/UmbracoRequireHttpsAttribute.cs | 40 --- src/Umbraco.Web/Umbraco.Web.csproj | 4 - 28 files changed, 313 insertions(+), 902 deletions(-) rename src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/{HijackedRouteEvaluatorTests.cs => ControllerActionSearcherTests.cs} (94%) rename src/Umbraco.Web.Website/Routing/{HijackedRouteResult.cs => ControllerActionSearchResult.cs} (53%) rename src/Umbraco.Web.Website/Routing/{HijackedRouteEvaluator.cs => ControllerActionSearcher.cs} (81%) create mode 100644 src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs delete mode 100644 src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs delete mode 100644 src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs delete mode 100644 src/Umbraco.Web/Mvc/UmbracoPageResult.cs delete mode 100644 src/Umbraco.Web/Mvc/UmbracoRequireHttpsAttribute.cs diff --git a/src/Umbraco.Core/Constants-Web.cs b/src/Umbraco.Core/Constants-Web.cs index 8199d9fbd0..6d98a86580 100644 --- a/src/Umbraco.Core/Constants-Web.cs +++ b/src/Umbraco.Core/Constants-Web.cs @@ -7,8 +7,6 @@ namespace Umbraco.Core /// public static class Web { - public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def"; - /// /// The preview cookie name /// diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs index 01b6032c36..f4e3aed39f 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs @@ -60,22 +60,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common.ModelBinders // Arrange IPublishedContent pc = CreatePublishedContent(); ModelBindingContext bindingContext = CreateBindingContextForUmbracoRequest(typeof(ContentModel), pc); - bindingContext.ActionContext.RouteData.Values.Remove(Constants.Web.UmbracoRouteDefinitionDataToken); - - // Act - await _contentModelBinder.BindModelAsync(bindingContext); - - // Assert - Assert.False(bindingContext.Result.IsModelSet); - } - - [Test] - public async Task Does_Not_Bind_Model_When_UmbracoToken_Has_Incorrect_Model() - { - // Arrange - IPublishedContent pc = CreatePublishedContent(); - ModelBindingContext bindingContext = CreateBindingContextForUmbracoRequest(typeof(ContentModel), pc); - bindingContext.ActionContext.RouteData.Values[Constants.Web.UmbracoRouteDefinitionDataToken] = new NonContentModel(); + bindingContext.ActionContext.HttpContext.Features.Set(null); // Act await _contentModelBinder.BindModelAsync(bindingContext); @@ -220,9 +205,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common.ModelBinders var httpContext = new DefaultHttpContext(); var routeData = new RouteData(); - routeData.Values.Add(Constants.Web.UmbracoRouteDefinitionDataToken, new UmbracoRouteValues(publishedRequest)); - { - } + httpContext.Features.Set(new UmbracoRouteValues(publishedRequest)); var actionContext = new ActionContext(httpContext, routeData, new ActionDescriptor()); var metadataProvider = new EmptyModelMetadataProvider(); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs index e286603f1c..53ae713564 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Moq; @@ -126,15 +127,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Controllers var routeDefinition = new UmbracoRouteValues(publishedRequest); - var routeData = new RouteData(); - routeData.Values.Add(CoreConstants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); + var httpContext = new DefaultHttpContext(); + httpContext.Features.Set(routeDefinition); var ctrl = new TestSurfaceController(umbracoContextAccessor, Mock.Of(), Mock.Of()) { ControllerContext = new ControllerContext() { - HttpContext = Mock.Of(), - RouteData = routeData + HttpContext = httpContext, + RouteData = new RouteData() } }; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/ControllerActionSearcherTests.cs similarity index 94% rename from src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/ControllerActionSearcherTests.cs index 2d96476b30..9556640364 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/ControllerActionSearcherTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing { [TestFixture] - public class HijackedRouteEvaluatorTests + public class ControllerActionSearcherTests { private class TestActionDescriptorCollectionProvider : ActionDescriptorCollectionProvider { @@ -88,11 +88,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing [TestCase("Custom", "Render1", nameof(Render1Controller.Custom), true)] public void Matches_Controller(string action, string controller, string resultAction, bool matches) { - var evaluator = new HijackedRouteEvaluator( - new NullLogger(), + var query = new ControllerActionSearcher( + new NullLogger(), GetActionDescriptors()); - HijackedRouteResult result = evaluator.Evaluate(controller, action); + ControllerActionSearchResult result = query.Find(controller, action); Assert.AreEqual(matches, result.Success); if (matches) { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs index a531c77fe1..e3147220bb 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Routing; @@ -49,7 +50,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing TestHelper.GetHostingEnvironment(), state, routeValuesFactory ?? Mock.Of(), - filter ?? Mock.Of(x => x.IsDocumentRequest(It.IsAny()) == true)); + filter ?? Mock.Of(x => x.IsDocumentRequest(It.IsAny()) == true), + Mock.Of(), + Mock.Of()); return transformer; } @@ -74,7 +77,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing typeof(TestController)); private IUmbracoRouteValuesFactory GetRouteValuesFactory(IPublishedRequest request) - => Mock.Of(x => x.Create(It.IsAny(), It.IsAny(), It.IsAny()) == GetRouteValues(request)); + => Mock.Of(x => x.Create(It.IsAny(), It.IsAny()) == GetRouteValues(request)); private IPublishedRouter GetRouter(IPublishedRequest request) => Mock.Of(x => x.RouteRequestAsync(It.IsAny(), It.IsAny()) == Task.FromResult(request)); @@ -140,6 +143,25 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing Assert.AreEqual(request, umbracoContext.PublishedRequest); } + [Test] + public async Task Assigns_UmbracoRouteValues_To_HttpContext_Feature() + { + IUmbracoContext umbracoContext = GetUmbracoContext(true); + IPublishedRequest request = Mock.Of(); + + UmbracoRouteValueTransformer transformer = GetTransformerWithRunState( + Mock.Of(x => x.UmbracoContext == umbracoContext), + router: GetRouter(request), + routeValuesFactory: GetRouteValuesFactory(request)); + + var httpContext = new DefaultHttpContext(); + RouteValueDictionary result = await transformer.TransformAsync(httpContext, new RouteValueDictionary()); + + UmbracoRouteValues routeVals = httpContext.Features.Get(); + Assert.IsNotNull(routeVals); + Assert.AreEqual(routeVals.PublishedRequest, umbracoContext.PublishedRequest); + } + [Test] public async Task Assigns_Values_To_RouteValueDictionary() { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs index 17ce59862f..2c8dd3b395 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs @@ -39,8 +39,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing renderingDefaults, Mock.Of(), new UmbracoFeatures(), - new HijackedRouteEvaluator( - new NullLogger(), + new ControllerActionSearcher( + new NullLogger(), Mock.Of()), publishedRouter.Object); @@ -56,7 +56,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing UmbracoRouteValuesFactory factory = GetFactory(out Mock publishedRouter, out _); - UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), new RouteValueDictionary(), request); + UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), request); // The request has content, no template, no hijacked route and no disabled template features so UpdateRequestToNotFound will be called publishedRouter.Verify(m => m.UpdateRequestToNotFound(It.IsAny()), Times.Once); @@ -73,11 +73,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing UmbracoRouteValuesFactory factory = GetFactory(out _, out UmbracoRenderingDefaults renderingDefaults); var routeVals = new RouteValueDictionary(); - UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), routeVals, request); + UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), request); Assert.IsNotNull(result); - Assert.IsTrue(routeVals.ContainsKey(Constants.Web.UmbracoRouteDefinitionDataToken)); - Assert.AreEqual(result, routeVals[Constants.Web.UmbracoRouteDefinitionDataToken]); Assert.AreEqual(renderingDefaults.DefaultControllerType, result.ControllerType); Assert.AreEqual(UmbracoRouteValues.DefaultActionName, result.ActionName); Assert.IsNull(result.TemplateName); diff --git a/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs b/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs index a33dba9ca6..a2c403bf7b 100644 --- a/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs +++ b/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs @@ -17,12 +17,13 @@ namespace Umbraco.Web.Common.Controllers /// protected UmbracoRouteValues GetUmbracoRouteValues(ResultExecutingContext context) { - if (!context.RouteData.Values.TryGetValue(Core.Constants.Web.UmbracoRouteDefinitionDataToken, out var def)) + UmbracoRouteValues routeVals = context.HttpContext.Features.Get(); + if (routeVals == null) { - throw new InvalidOperationException($"No route value found with key {Core.Constants.Web.UmbracoRouteDefinitionDataToken}"); + throw new InvalidOperationException($"No {nameof(UmbracoRouteValues)} feature was found in the HttpContext"); } - return (UmbracoRouteValues)def; + return routeVals; } /// diff --git a/src/Umbraco.Web.Common/Controllers/RenderController.cs b/src/Umbraco.Web.Common/Controllers/RenderController.cs index d9a2d05979..2359d6d13c 100644 --- a/src/Umbraco.Web.Common/Controllers/RenderController.cs +++ b/src/Umbraco.Web.Common/Controllers/RenderController.cs @@ -71,11 +71,11 @@ namespace Umbraco.Web.Common.Controllers return _umbracoRouteValues; } - _umbracoRouteValues = HttpContext.GetRouteValue(Core.Constants.Web.UmbracoRouteDefinitionDataToken) as UmbracoRouteValues; + _umbracoRouteValues = HttpContext.Features.Get(); if (_umbracoRouteValues == null) { - throw new InvalidOperationException($"No route value found with key {Core.Constants.Web.UmbracoRouteDefinitionDataToken}"); + throw new InvalidOperationException($"No {nameof(UmbracoRouteValues)} feature was found in the HttpContext"); } return _umbracoRouteValues; diff --git a/src/Umbraco.Web.Common/Localization/UmbracoPublishedContentCultureProvider.cs b/src/Umbraco.Web.Common/Localization/UmbracoPublishedContentCultureProvider.cs index 7322ad2869..66177e965a 100644 --- a/src/Umbraco.Web.Common/Localization/UmbracoPublishedContentCultureProvider.cs +++ b/src/Umbraco.Web.Common/Localization/UmbracoPublishedContentCultureProvider.cs @@ -29,7 +29,8 @@ namespace Umbraco.Web.Common.Localization /// public override Task DetermineProviderCultureResult(HttpContext httpContext) { - if (httpContext.GetRouteValue(Core.Constants.Web.UmbracoRouteDefinitionDataToken) is UmbracoRouteValues routeValues) + UmbracoRouteValues routeValues = httpContext.Features.Get(); + if (routeValues != null) { string culture = routeValues.PublishedRequest?.Culture; if (culture != null) diff --git a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs index cc6678abfc..b93978693b 100644 --- a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs +++ b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs @@ -30,8 +30,8 @@ namespace Umbraco.Web.Common.ModelBinders // only IPublishedContent will ever exist in the request so when this model binder is used as an IModelBinder // in the aspnet pipeline it will really only support converting from IPublishedContent which is contained // in the UmbracoRouteValues --> IContentModel - if (!bindingContext.ActionContext.RouteData.Values.TryGetValue(Core.Constants.Web.UmbracoRouteDefinitionDataToken, out var source) - || !(source is UmbracoRouteValues umbracoRouteValues)) + UmbracoRouteValues umbracoRouteValues = bindingContext.HttpContext.Features.Get(); + if (umbracoRouteValues == null) { return Task.CompletedTask; } diff --git a/src/Umbraco.Web.Common/Security/EncryptionHelper.cs b/src/Umbraco.Web.Common/Security/EncryptionHelper.cs index 300afd530d..9dc1cd7497 100644 --- a/src/Umbraco.Web.Common/Security/EncryptionHelper.cs +++ b/src/Umbraco.Web.Common/Security/EncryptionHelper.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using System.Net; using System.Web; @@ -12,64 +13,80 @@ namespace Umbraco.Web.Common.Security { public class EncryptionHelper { + // TODO: Decide if these belong here... I don't think so since this all has to do with surface controller routes + // could also just be injected too.... + private static IDataProtector CreateDataProtector(IDataProtectionProvider dataProtectionProvider) - { - return dataProtectionProvider.CreateProtector(nameof(EncryptionHelper)); - } + => dataProtectionProvider.CreateProtector(nameof(EncryptionHelper)); public static string Decrypt(string encryptedString, IDataProtectionProvider dataProtectionProvider) - { - return CreateDataProtector(dataProtectionProvider).Unprotect(encryptedString); - } + => CreateDataProtector(dataProtectionProvider).Unprotect(encryptedString); public static string Encrypt(string plainString, IDataProtectionProvider dataProtectionProvider) - { - return CreateDataProtector(dataProtectionProvider).Protect(plainString); - } + => CreateDataProtector(dataProtectionProvider).Protect(plainString); /// /// 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. /// - /// - /// - /// - /// - /// - /// public static string CreateEncryptedRouteString(IDataProtectionProvider dataProtectionProvider, string controllerName, string controllerAction, string area, object additionalRouteVals = null) { - if (dataProtectionProvider == null) throw new ArgumentNullException(nameof(dataProtectionProvider)); - 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)); + if (dataProtectionProvider is null) + { + throw new ArgumentNullException(nameof(dataProtectionProvider)); + } - //need to create a params string as Base64 to put into our hidden field to use during the routes + if (string.IsNullOrEmpty(controllerName)) + { + throw new ArgumentException($"'{nameof(controllerName)}' cannot be null or empty.", nameof(controllerName)); + } + + if (string.IsNullOrEmpty(controllerAction)) + { + throw new ArgumentException($"'{nameof(controllerAction)}' cannot be null or empty.", nameof(controllerAction)); + } + + if (area is 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 = $"{ViewConstants.ReservedAdditionalKeys.Controller}={WebUtility.UrlEncode(controllerName)}&{ViewConstants.ReservedAdditionalKeys.Action}={WebUtility.UrlEncode(controllerAction)}&{ViewConstants.ReservedAdditionalKeys.Area}={area}"; - //checking if the additional route values is already a dictionary and convert to querystring + // 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 Encrypt(surfaceRouteParams, dataProtectionProvider); } public static bool DecryptAndValidateEncryptedRouteString(IDataProtectionProvider dataProtectionProvider, string encryptedString, out IDictionary parts) { - if (dataProtectionProvider == null) throw new ArgumentNullException(nameof(dataProtectionProvider)); + if (dataProtectionProvider == null) + { + throw new ArgumentNullException(nameof(dataProtectionProvider)); + } + string decryptedString; try { @@ -81,22 +98,32 @@ namespace Umbraco.Web.Common.Security parts = null; return false; } - var parsedQueryString = HttpUtility.ParseQueryString(decryptedString); + + NameValueCollection parsedQueryString = HttpUtility.ParseQueryString(decryptedString); parts = new Dictionary(); foreach (var key in parsedQueryString.AllKeys) { parts[key] = parsedQueryString[key]; } - //validate all required keys exist - //the controller + + // validate all required keys exist + // the controller if (parts.All(x => x.Key != ViewConstants.ReservedAdditionalKeys.Controller)) + { return false; - //the action + } + + // the action if (parts.All(x => x.Key != ViewConstants.ReservedAdditionalKeys.Action)) + { return false; - //the area + } + + // the area if (parts.All(x => x.Key != ViewConstants.ReservedAdditionalKeys.Area)) + { return false; + } return true; } diff --git a/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs b/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs index abf269e062..65af4a2df5 100644 --- a/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs +++ b/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; @@ -13,6 +14,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Extensions; +using Umbraco.Web.Common.Routing; namespace Umbraco.Web.Website.ActionResults { @@ -33,13 +35,15 @@ namespace Umbraco.Web.Website.ActionResults var routeData = context.RouteData; ResetRouteData(routeData); - ValidateRouteData(routeData); + ValidateRouteData(context); - var factory = context.HttpContext.RequestServices.GetRequiredService(); + IControllerFactory factory = context.HttpContext.RequestServices.GetRequiredService(); Controller controller = null; if (!(context is ControllerContext controllerContext)) - return Task.FromCanceled(new System.Threading.CancellationToken()); + { + return Task.FromCanceled(CancellationToken.None); + } try { @@ -97,9 +101,10 @@ namespace Umbraco.Web.Website.ActionResults /// /// Validate that the current page execution is not being handled by the normal umbraco routing system /// - private static void ValidateRouteData(RouteData routeData) + private static void ValidateRouteData(ActionContext actionContext) { - if (routeData.Values.ContainsKey(Constants.Web.UmbracoRouteDefinitionDataToken) == false) + UmbracoRouteValues umbracoRouteValues = actionContext.HttpContext.Features.Get(); + if (umbracoRouteValues == null) { throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + " in the context of an Http POST when using a SurfaceController form"); @@ -114,7 +119,9 @@ namespace Umbraco.Web.Website.ActionResults controller.ViewData.ModelState.Merge(context.ModelState); foreach (var d in controller.ViewData) + { controller.ViewData[d.Key] = d.Value; + } // We cannot simply merge the temp data because during controller execution it will attempt to 'load' temp data // but since it has not been saved, there will be nothing to load and it will revert to nothing, so the trick is @@ -135,7 +142,9 @@ namespace Umbraco.Web.Website.ActionResults private static Controller CreateController(ControllerContext context, IControllerFactory factory) { if (!(factory.CreateController(context) is Controller controller)) + { throw new InvalidOperationException("Could not create controller with name " + context.ActionDescriptor.ControllerName + "."); + } return controller; } @@ -146,7 +155,9 @@ namespace Umbraco.Web.Website.ActionResults private static void CleanupController(ControllerContext context, Controller controller, IControllerFactory factory) { if (!(controller is null)) + { factory.ReleaseController(context, controller); + } controller?.DisposeIfDisposable(); } diff --git a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs index edf5428f9b..ceb8a012cf 100644 --- a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs +++ b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; @@ -38,14 +39,13 @@ namespace Umbraco.Web.Website.Controllers { get { - var routeDefAttempt = TryGetRouteDefinitionFromAncestorViewContexts(); - if (routeDefAttempt.Success == false) + UmbracoRouteValues umbracoRouteValues = HttpContext.Features.Get(); + if (umbracoRouteValues == null) { - throw routeDefAttempt.Exception; + throw new InvalidOperationException($"No {nameof(UmbracoRouteValues)} feature was found in the HttpContext"); } - var routeDef = routeDefAttempt.Result; - return routeDef.PublishedRequest.PublishedContent; + return umbracoRouteValues.PublishedRequest.PublishedContent; } } @@ -101,24 +101,5 @@ namespace Umbraco.Web.Website.Controllers /// protected UmbracoPageResult CurrentUmbracoPage() => new UmbracoPageResult(ProfilingLogger); - - /// - /// we need to recursively find the route definition based on the parent view context - /// - private Attempt TryGetRouteDefinitionFromAncestorViewContexts() - { - var currentContext = ControllerContext; - while (!(currentContext is null)) - { - var currentRouteData = currentContext.RouteData; - if (currentRouteData.Values.ContainsKey(Constants.Web.UmbracoRouteDefinitionDataToken)) - { - return Attempt.Succeed((UmbracoRouteValues)currentRouteData.Values[Constants.Web.UmbracoRouteDefinitionDataToken]); - } - } - - return Attempt.Fail( - new InvalidOperationException("Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request")); - } } } diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 42174ecb73..b1d21e87b9 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Website.DependencyInjection builder.Services.AddDataProtection(); builder.Services.AddScoped(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs index f79648b19a..ac6154f645 100644 --- a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs @@ -243,15 +243,12 @@ namespace Umbraco.Extensions return htmlHelper.ActionLink(actionName, metaData.ControllerName, routeVals); } - #region BeginUmbracoForm - /// /// Used for rendering out the Form for BeginUmbracoForm /// internal class UmbracoForm : MvcForm { private readonly ViewContext _viewContext; - private bool _disposed; private readonly string _encryptedString; private readonly string _controllerName; @@ -272,15 +269,8 @@ namespace Umbraco.Extensions _encryptedString = EncryptionHelper.CreateEncryptedRouteString(GetRequiredService(viewContext), controllerName, controllerAction, area, additionalRouteVals); } - protected new void Dispose() + protected override void GenerateEndForm() { - if (_disposed) - { - return; - } - - _disposed = true; - // Detect if the call is targeting UmbRegisterController/UmbProfileController/UmbLoginStatusController/UmbLoginController and if it is we automatically output a AntiForgeryToken() // We have a controllerName and area so we can match if (_controllerName == "UmbRegister" @@ -295,7 +285,7 @@ namespace Umbraco.Extensions // write out the hidden surface form routes _viewContext.Writer.Write(""); - base.Dispose(); + base.GenerateEndForm(); } } @@ -710,7 +700,6 @@ namespace Umbraco.Extensions return theForm; } - #endregion #region If diff --git a/src/Umbraco.Web.Website/Routing/HijackedRouteResult.cs b/src/Umbraco.Web.Website/Routing/ControllerActionSearchResult.cs similarity index 53% rename from src/Umbraco.Web.Website/Routing/HijackedRouteResult.cs rename to src/Umbraco.Web.Website/Routing/ControllerActionSearchResult.cs index f88bdfa2fd..2c2f4802df 100644 --- a/src/Umbraco.Web.Website/Routing/HijackedRouteResult.cs +++ b/src/Umbraco.Web.Website/Routing/ControllerActionSearchResult.cs @@ -1,21 +1,16 @@ -using System; +using System; namespace Umbraco.Web.Website.Routing { /// - /// The result from evaluating if a route can be hijacked + /// The result from querying a controller/action in the existing routes /// - public class HijackedRouteResult + public class ControllerActionSearchResult { /// - /// Returns a failed result + /// Initializes a new instance of the class. /// - public static HijackedRouteResult Failed() => new HijackedRouteResult(false, null, null, null); - - /// - /// Initializes a new instance of the class. - /// - public HijackedRouteResult( + private ControllerActionSearchResult( bool success, string controllerName, Type controllerType, @@ -28,7 +23,18 @@ namespace Umbraco.Web.Website.Routing } /// - /// Gets a value indicating if the route could be hijacked + /// Initializes a new instance of the class. + /// + public ControllerActionSearchResult( + string controllerName, + Type controllerType, + string actionName) + : this(true, controllerName, controllerType, actionName) + { + } + + /// + /// Gets a value indicating whether the route could be hijacked /// public bool Success { get; } @@ -46,5 +52,10 @@ namespace Umbraco.Web.Website.Routing /// Gets the Acton name /// public string ActionName { get; } + + /// + /// Returns a failed result + /// + public static ControllerActionSearchResult Failed() => new ControllerActionSearchResult(false, null, null, null); } } diff --git a/src/Umbraco.Web.Website/Routing/HijackedRouteEvaluator.cs b/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs similarity index 81% rename from src/Umbraco.Web.Website/Routing/HijackedRouteEvaluator.cs rename to src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs index 79036a01e1..f38c4676c8 100644 --- a/src/Umbraco.Web.Website/Routing/HijackedRouteEvaluator.cs +++ b/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs @@ -11,19 +11,19 @@ using Umbraco.Web.Common.Controllers; namespace Umbraco.Web.Website.Routing { /// - /// Determines if a custom controller can hijack the current route + /// Used to find a controller/action in the current available routes /// - public class HijackedRouteEvaluator + public class ControllerActionSearcher : IControllerActionSearcher { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider; private const string DefaultActionName = nameof(RenderController.Index); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public HijackedRouteEvaluator( - ILogger logger, + public ControllerActionSearcher( + ILogger logger, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) { _logger = logger; @@ -33,7 +33,8 @@ namespace Umbraco.Web.Website.Routing /// /// Determines if a custom controller can hijack the current route /// - public HijackedRouteResult Evaluate(string controller, string action) + /// The controller type to find + public ControllerActionSearchResult Find(string controller, string action) { IReadOnlyList candidates = FindControllerCandidates(controller, action, DefaultActionName); @@ -45,8 +46,8 @@ namespace Umbraco.Web.Website.Routing { ControllerActionDescriptor controllerDescriptor = customControllerCandidates[0]; - // ensure the controller is of type IRenderController and ControllerBase - if (TypeHelper.IsTypeAssignableFrom(controllerDescriptor.ControllerTypeInfo) + // ensure the controller is of type T and ControllerBase + if (TypeHelper.IsTypeAssignableFrom(controllerDescriptor.ControllerTypeInfo) && TypeHelper.IsTypeAssignableFrom(controllerDescriptor.ControllerTypeInfo)) { // now check if the custom action matches @@ -61,8 +62,7 @@ namespace Umbraco.Web.Website.Routing } // it's a hijacked route with a custom controller, so return the the values - return new HijackedRouteResult( - true, + return new ControllerActionSearchResult( controllerDescriptor.ControllerName, controllerDescriptor.ControllerTypeInfo, resultingAction); @@ -73,7 +73,7 @@ namespace Umbraco.Web.Website.Routing "The current Document Type {ContentTypeAlias} matches a locally declared controller of type {ControllerName}. Custom Controllers for Umbraco routing must implement '{UmbracoRenderController}' and inherit from '{UmbracoControllerBase}'.", controller, controllerDescriptor.ControllerTypeInfo.FullName, - typeof(IRenderController).FullName, + typeof(T).FullName, typeof(ControllerBase).FullName); // we cannot route to this custom controller since it is not of the correct type so we'll continue with the defaults @@ -81,7 +81,7 @@ namespace Umbraco.Web.Website.Routing } } - return HijackedRouteResult.Failed(); + return ControllerActionSearchResult.Failed(); } /// diff --git a/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs b/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs new file mode 100644 index 0000000000..36b4382cc2 --- /dev/null +++ b/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Web.Website.Routing +{ + public interface IControllerActionSearcher + { + ControllerActionSearchResult Find(string controller, string action); + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.Website/Routing/IUmbracoRouteValuesFactory.cs b/src/Umbraco.Web.Website/Routing/IUmbracoRouteValuesFactory.cs index 7af41d865b..f584627e31 100644 --- a/src/Umbraco.Web.Website/Routing/IUmbracoRouteValuesFactory.cs +++ b/src/Umbraco.Web.Website/Routing/IUmbracoRouteValuesFactory.cs @@ -13,6 +13,6 @@ namespace Umbraco.Web.Website.Routing /// /// Creates /// - UmbracoRouteValues Create(HttpContext httpContext, RouteValueDictionary values, IPublishedRequest request); + UmbracoRouteValues Create(HttpContext httpContext, IPublishedRequest request); } } diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs index af23105099..a4ab61b3cc 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs @@ -1,14 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; using System.Threading.Tasks; +using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Extensions; using Umbraco.Web.Common.Routing; +using Umbraco.Web.Common.Security; using Umbraco.Web.Routing; using Umbraco.Web.Website.Controllers; using RouteDirection = Umbraco.Web.Routing.RouteDirection; @@ -35,6 +43,10 @@ namespace Umbraco.Web.Website.Routing private readonly IRuntimeState _runtime; private readonly IUmbracoRouteValuesFactory _routeValuesFactory; private readonly IRoutableDocumentFilter _routableDocumentFilter; + private readonly IDataProtectionProvider _dataProtectionProvider; + private readonly IControllerActionSearcher _controllerActionSearcher; + private const string ControllerToken = "controller"; + private const string ActionToken = "action"; /// /// Initializes a new instance of the class. @@ -47,21 +59,25 @@ namespace Umbraco.Web.Website.Routing IHostingEnvironment hostingEnvironment, IRuntimeState runtime, IUmbracoRouteValuesFactory routeValuesFactory, - IRoutableDocumentFilter routableDocumentFilter) + IRoutableDocumentFilter routableDocumentFilter, + IDataProtectionProvider dataProtectionProvider, + IControllerActionSearcher controllerActionSearcher) { if (globalSettings is null) { - throw new System.ArgumentNullException(nameof(globalSettings)); + throw new ArgumentNullException(nameof(globalSettings)); } - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - _umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor)); - _publishedRouter = publishedRouter ?? throw new System.ArgumentNullException(nameof(publishedRouter)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); + _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); _globalSettings = globalSettings.Value; - _hostingEnvironment = hostingEnvironment ?? throw new System.ArgumentNullException(nameof(hostingEnvironment)); - _runtime = runtime ?? throw new System.ArgumentNullException(nameof(runtime)); - _routeValuesFactory = routeValuesFactory ?? throw new System.ArgumentNullException(nameof(routeValuesFactory)); - _routableDocumentFilter = routableDocumentFilter ?? throw new System.ArgumentNullException(nameof(routableDocumentFilter)); + _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); + _runtime = runtime ?? throw new ArgumentNullException(nameof(runtime)); + _routeValuesFactory = routeValuesFactory ?? throw new ArgumentNullException(nameof(routeValuesFactory)); + _routableDocumentFilter = routableDocumentFilter ?? throw new ArgumentNullException(nameof(routableDocumentFilter)); + _dataProtectionProvider = dataProtectionProvider; + _controllerActionSearcher = controllerActionSearcher; } /// @@ -87,23 +103,33 @@ namespace Umbraco.Web.Website.Routing // Check if there is no existing content and return the no content controller if (!_umbracoContextAccessor.UmbracoContext.Content.HasContent()) { - values["controller"] = ControllerExtensions.GetControllerName(); - values["action"] = nameof(RenderNoContentController.Index); + values[ControllerToken] = ControllerExtensions.GetControllerName(); + values[ActionToken] = nameof(RenderNoContentController.Index); - return await Task.FromResult(values); + return values; } IPublishedRequest publishedRequest = await RouteRequestAsync(_umbracoContextAccessor.UmbracoContext); - UmbracoRouteValues routeDef = _routeValuesFactory.Create(httpContext, values, publishedRequest); + UmbracoRouteValues umbracoRouteValues = _routeValuesFactory.Create(httpContext, publishedRequest); - values["controller"] = routeDef.ControllerName; - if (string.IsNullOrWhiteSpace(routeDef.ActionName) == false) + // Store the route values as a httpcontext feature + httpContext.Features.Set(umbracoRouteValues); + + // Need to check if there is form data being posted back to an Umbraco URL + PostedDataProxyInfo postedInfo = GetFormInfo(httpContext, values); + if (postedInfo != null) { - values["action"] = routeDef.ActionName; + return HandlePostedValues(postedInfo, httpContext, values); } - return await Task.FromResult(values); + values[ControllerToken] = umbracoRouteValues.ControllerName; + if (string.IsNullOrWhiteSpace(umbracoRouteValues.ActionName) == false) + { + values[ActionToken] = umbracoRouteValues.ActionName; + } + + return values; } private async Task RouteRequestAsync(IUmbracoContext umbracoContext) @@ -123,5 +149,92 @@ namespace Umbraco.Web.Website.Routing return routedRequest; } + + /// + /// Checks the request and query strings to see if it matches the definition of having a Surface controller + /// posted/get value, if so, then we return a PostedDataProxyInfo object with the correct information. + /// + private PostedDataProxyInfo GetFormInfo(HttpContext httpContext, RouteValueDictionary values) + { + if (httpContext is null) + { + throw new ArgumentNullException(nameof(httpContext)); + } + + // if it is a POST/GET then a value must be in the request + if (!httpContext.Request.Query.TryGetValue("ufprt", out StringValues encodedVal) + && (!httpContext.Request.HasFormContentType || !httpContext.Request.Form.TryGetValue("ufprt", out encodedVal))) + { + return null; + } + + if (!EncryptionHelper.DecryptAndValidateEncryptedRouteString( + _dataProtectionProvider, + encodedVal, + out IDictionary decodedParts)) + { + return null; + } + + // Get all route values that are not the default ones and add them separately so they eventually get to action parameters + foreach (KeyValuePair item in decodedParts.Where(x => ReservedAdditionalKeys.AllKeys.Contains(x.Key) == false)) + { + values[item.Key] = item.Value; + } + + // return the proxy info without the surface id... could be a local controller. + return new PostedDataProxyInfo + { + ControllerName = WebUtility.UrlDecode(decodedParts.First(x => x.Key == ReservedAdditionalKeys.Controller).Value), + ActionName = WebUtility.UrlDecode(decodedParts.First(x => x.Key == ReservedAdditionalKeys.Action).Value), + Area = WebUtility.UrlDecode(decodedParts.First(x => x.Key == ReservedAdditionalKeys.Area).Value), + }; + } + + private RouteValueDictionary HandlePostedValues(PostedDataProxyInfo postedInfo, HttpContext httpContext, RouteValueDictionary values) + { + // set the standard route values/tokens + values[ControllerToken] = postedInfo.ControllerName; + values[ActionToken] = postedInfo.ActionName; + + ControllerActionSearchResult surfaceControllerQueryResult = _controllerActionSearcher.Find(postedInfo.ControllerName, postedInfo.ActionName); + + if (surfaceControllerQueryResult == null || !surfaceControllerQueryResult.Success) + { + throw new InvalidOperationException("Could not find a Surface controller route in the RouteTable for controller name " + postedInfo.ControllerName); + } + + // set the area if one is there. + if (!postedInfo.Area.IsNullOrWhiteSpace()) + { + values["area"] = postedInfo.Area; + } + + return values; + } + + private class PostedDataProxyInfo + { + public string ControllerName { get; set; } + + public string ActionName { get; set; } + + public string Area { get; set; } + } + + // Define reserved dictionary keys for controller, action and area specified in route additional values data + private static class ReservedAdditionalKeys + { + internal static readonly string[] AllKeys = new[] + { + Controller, + Action, + Area + }; + + internal const string Controller = "c"; + internal const string Action = "a"; + internal const string Area = "ar"; + } } } diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs index d26216204e..9d75733f1f 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Routing; using Umbraco.Core; using Umbraco.Core.Strings; using Umbraco.Extensions; +using Umbraco.Web.Common.Controllers; using Umbraco.Web.Common.Routing; using Umbraco.Web.Features; using Umbraco.Web.Routing; @@ -20,7 +21,7 @@ namespace Umbraco.Web.Website.Routing private readonly IUmbracoRenderingDefaults _renderingDefaults; private readonly IShortStringHelper _shortStringHelper; private readonly UmbracoFeatures _umbracoFeatures; - private readonly HijackedRouteEvaluator _hijackedRouteEvaluator; + private readonly IControllerActionSearcher _controllerActionSearcher; private readonly IPublishedRouter _publishedRouter; private readonly Lazy _defaultControllerName; @@ -31,13 +32,13 @@ namespace Umbraco.Web.Website.Routing IUmbracoRenderingDefaults renderingDefaults, IShortStringHelper shortStringHelper, UmbracoFeatures umbracoFeatures, - HijackedRouteEvaluator hijackedRouteEvaluator, + IControllerActionSearcher controllerActionSearcher, IPublishedRouter publishedRouter) { _renderingDefaults = renderingDefaults; _shortStringHelper = shortStringHelper; _umbracoFeatures = umbracoFeatures; - _hijackedRouteEvaluator = hijackedRouteEvaluator; + _controllerActionSearcher = controllerActionSearcher; _publishedRouter = publishedRouter; _defaultControllerName = new Lazy(() => ControllerExtensions.GetControllerName(_renderingDefaults.DefaultControllerType)); } @@ -48,18 +49,13 @@ namespace Umbraco.Web.Website.Routing protected string DefaultControllerName => _defaultControllerName.Value; /// - public UmbracoRouteValues Create(HttpContext httpContext, RouteValueDictionary values, IPublishedRequest request) + public UmbracoRouteValues Create(HttpContext httpContext, IPublishedRequest request) { if (httpContext is null) { throw new ArgumentNullException(nameof(httpContext)); } - if (values is null) - { - throw new ArgumentNullException(nameof(values)); - } - if (request is null) { throw new ArgumentNullException(nameof(request)); @@ -90,9 +86,6 @@ namespace Umbraco.Web.Website.Routing def = CheckNoTemplate(def); - // store the route definition - values.TryAdd(Constants.Web.UmbracoRouteDefinitionDataToken, def); - return def; } @@ -106,7 +99,7 @@ namespace Umbraco.Web.Website.Routing var customControllerName = request.PublishedContent?.ContentType?.Alias; if (customControllerName != null) { - HijackedRouteResult hijackedResult = _hijackedRouteEvaluator.Evaluate(customControllerName, def.TemplateName); + ControllerActionSearchResult hijackedResult = _controllerActionSearcher.Find(customControllerName, def.TemplateName); if (hijackedResult.Success) { return new UmbracoRouteValues( diff --git a/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs b/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs deleted file mode 100644 index 4658910ab0..0000000000 --- a/src/Umbraco.Web/Mvc/RedirectToUmbracoPageResult.cs +++ /dev/null @@ -1,278 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; -using Umbraco.Web.Routing; - -namespace Umbraco.Web.Mvc -{ - /// - /// Redirects to an Umbraco page by Id or Entity - /// - /// Migrated already to .Net Core - public class RedirectToUmbracoPageResult : ActionResult - { - private IPublishedContent _publishedContent; - private readonly int _pageId; - private readonly Guid _key; - private NameValueCollection _queryStringValues; - private IPublishedUrlProvider _publishedUrlProvider; - private string _url; - - public string Url - { - get - { - if (!_url.IsNullOrWhiteSpace()) return _url; - - if (PublishedContent == null) - { - throw new InvalidOperationException(string.Format("Cannot redirect, no entity was found for id {0}", _pageId)); - } - - var result = _publishedUrlProvider.GetUrl(PublishedContent.Id); - if (result != "#") - { - _url = result; - return _url; - } - - throw new InvalidOperationException(string.Format("Could not route to entity with id {0}, the NiceUrlProvider could not generate a URL", _pageId)); - - } - } - - public int PageId - { - get { return _pageId; } - } - - public Guid Key - { - get { return _key; } - } - public IPublishedContent PublishedContent - { - get - { - if (_publishedContent != null) return _publishedContent; - - if (_pageId != default(int)) - { - _publishedContent = Current.UmbracoContext.Content.GetById(_pageId); - } - - else if (_key != default(Guid)) - { - _publishedContent = Current.UmbracoContext.Content.GetById(_key); - } - - return _publishedContent; - } - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - public RedirectToUmbracoPageResult(int pageId) - : this(pageId, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, NameValueCollection queryStringValues) - : this(pageId, queryStringValues, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, string queryString) - : this(pageId, queryString, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent) - : this(publishedContent, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, NameValueCollection queryStringValues) - : this(publishedContent, queryStringValues, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, string queryString) - : this(publishedContent, queryString, Current.PublishedUrlProvider) - { - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, IPublishedUrlProvider publishedUrlProvider) - { - _pageId = pageId; - _publishedUrlProvider = publishedUrlProvider; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, NameValueCollection queryStringValues, IPublishedUrlProvider publishedUrlProvider) - { - _pageId = pageId; - _queryStringValues = queryStringValues; - _publishedUrlProvider = publishedUrlProvider; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - /// - public RedirectToUmbracoPageResult(int pageId, string queryString, IPublishedUrlProvider publishedUrlProvider) - { - _pageId = pageId; - _queryStringValues = ParseQueryString(queryString); - _publishedUrlProvider = publishedUrlProvider; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(Guid key) - { - _key = key; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(Guid key, NameValueCollection queryStringValues) - { - _key = key; - _queryStringValues = queryStringValues; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(Guid key, string queryString) - { - _key = key; - _queryStringValues = ParseQueryString(queryString); - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, IPublishedUrlProvider publishedUrlProvider) - { - _publishedContent = publishedContent; - _pageId = publishedContent.Id; - _publishedUrlProvider = publishedUrlProvider; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, NameValueCollection queryStringValues, IPublishedUrlProvider publishedUrlProvider) - { - _publishedContent = publishedContent; - _pageId = publishedContent.Id; - _queryStringValues = queryStringValues; - _publishedUrlProvider = publishedUrlProvider; - } - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - /// - /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, string queryString, IPublishedUrlProvider publishedUrlProvider) - { - _publishedContent = publishedContent; - _pageId = publishedContent.Id; - _queryStringValues = ParseQueryString(queryString); - _publishedUrlProvider = publishedUrlProvider; - } - - public override void ExecuteResult(ControllerContext context) - { - if (context == null) throw new ArgumentNullException("context"); - - if (context.IsChildAction) - { - throw new InvalidOperationException("Cannot redirect from a Child Action"); - } - - var destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext); - - if (_queryStringValues != null && _queryStringValues.Count > 0) - { - destinationUrl = destinationUrl += "?" + string.Join("&", - _queryStringValues.AllKeys.Select(x => x + "=" + HttpUtility.UrlEncode(_queryStringValues[x]))); - } - - context.Controller.TempData.Keep(); - - context.HttpContext.Response.Redirect(destinationUrl, endResponse: false); - } - - private NameValueCollection ParseQueryString(string queryString) - { - if (!string.IsNullOrEmpty(queryString)) - { - return HttpUtility.ParseQueryString(queryString); - } - - return null; - } - } -} diff --git a/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs b/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs deleted file mode 100644 index 6f97bff534..0000000000 --- a/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace Umbraco.Web.Mvc -{ - /// - /// Redirects to the current URL rendering an Umbraco page including it's query strings - /// - /// - /// This is useful if you need to redirect - /// to the current page but the current page is actually a rewritten URL normally done with something like - /// Server.Transfer. It is also handy if you want to persist the query strings. - /// - /// Migrated already to .Net Core - public class RedirectToUmbracoUrlResult : ActionResult - { - private readonly IUmbracoContext _umbracoContext; - - /// - /// Creates a new RedirectToUmbracoResult - /// - /// - public RedirectToUmbracoUrlResult(IUmbracoContext umbracoContext) - { - _umbracoContext = umbracoContext; - } - - public override void ExecuteResult(ControllerContext context) - { - if (context == null) throw new ArgumentNullException("context"); - - if (context.IsChildAction) - { - throw new InvalidOperationException("Cannot redirect from a Child Action"); - } - - var destinationUrl = _umbracoContext.OriginalRequestUrl.PathAndQuery; - context.Controller.TempData.Keep(); - - context.HttpContext.Response.Redirect(destinationUrl, endResponse: false); - } - } -} diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index c88958d2fe..f5b536d259 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -3,16 +3,12 @@ using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; -using System.Web.SessionState; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Strings; using Umbraco.Web.Features; using Umbraco.Web.Models; using Umbraco.Web.Routing; -using Umbraco.Core.Strings; using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Mvc @@ -27,29 +23,21 @@ namespace Umbraco.Web.Mvc internal const string Area = "ar"; } - private readonly IControllerFactory _controllerFactory; - private readonly IShortStringHelper _shortStringHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IUmbracoContext _umbracoContext; public RenderRouteHandler(IUmbracoContextAccessor umbracoContextAccessor, IControllerFactory controllerFactory, IShortStringHelper shortStringHelper) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); - _controllerFactory = controllerFactory ?? throw new ArgumentNullException(nameof(controllerFactory)); - _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); } public RenderRouteHandler(IUmbracoContext umbracoContext, IControllerFactory controllerFactory, IShortStringHelper shortStringHelper) { _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); - _controllerFactory = controllerFactory ?? throw new ArgumentNullException(nameof(controllerFactory)); - _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); } private IUmbracoContext UmbracoContext => _umbracoContext ?? _umbracoContextAccessor.UmbracoContext; - private UmbracoFeatures Features => Current.Factory.GetRequiredService(); // TODO: inject - #region IRouteHandler Members /// @@ -74,26 +62,15 @@ namespace Umbraco.Web.Mvc #endregion - private void UpdateRouteDataForRequest(ContentModel contentModel, RequestContext requestContext) - { - if (contentModel == null) throw new ArgumentNullException(nameof(contentModel)); - if (requestContext == null) throw new ArgumentNullException(nameof(requestContext)); - - // requestContext.RouteData.DataTokens[Core.Constants.Web.UmbracoDataToken] = contentModel; - // the rest should not change -- it's only the published content that has changed - } - /// /// Checks the request and query strings to see if it matches the definition of having a Surface controller /// posted/get value, if so, then we return a PostedDataProxyInfo object with the correct information. /// - /// - /// internal static PostedDataProxyInfo GetFormInfo(RequestContext requestContext) { if (requestContext == null) throw new ArgumentNullException(nameof(requestContext)); - //if it is a POST/GET then a value must be in the request + // if it is a POST/GET then a value must be in the request if (requestContext.HttpContext.Request.QueryString["ufprt"].IsNullOrWhiteSpace() && requestContext.HttpContext.Request.Form["ufprt"].IsNullOrWhiteSpace()) { @@ -105,12 +82,12 @@ namespace Umbraco.Web.Mvc switch (requestContext.HttpContext.Request.RequestType) { case "POST": - //get the value from the request. - //this field will contain an encrypted version of the surface route vals. + // get the value from the request. + // this field will contain an encrypted version of the surface route vals. encodedVal = requestContext.HttpContext.Request.Form["ufprt"]; break; case "GET": - //this field will contain an encrypted version of the surface route vals. + // this field will contain an encrypted version of the surface route vals. encodedVal = requestContext.HttpContext.Request.QueryString["ufprt"]; break; default: @@ -144,8 +121,6 @@ namespace Umbraco.Web.Mvc /// Handles a posted form to an Umbraco URL and ensures the correct controller is routed to and that /// the right DataTokens are set. /// - /// - /// internal static IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo) { if (requestContext == null) throw new ArgumentNullException(nameof(requestContext)); diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index fa67248e7d..483461ae57 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -10,9 +10,6 @@ using Umbraco.Web.Composing; namespace Umbraco.Web.Mvc { - /// - /// Provides a base class for front-end add-in controllers. - /// /// Migrated already to .Net Core without MergeModelStateToChildAction and MergeParentContextViewData action filters /// TODO: Migrate MergeModelStateToChildAction and MergeParentContextViewData action filters [MergeModelStateToChildAction] @@ -26,197 +23,5 @@ namespace Umbraco.Web.Mvc : base(umbracoContextAccessor, databaseFactory, services, appCaches,profilingLogger) { } - /// - /// Redirects to the Umbraco page with the given id - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(int pageId) - { - return new RedirectToUmbracoPageResult(pageId, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(int pageId, NameValueCollection queryStringValues) - { - return new RedirectToUmbracoPageResult(pageId, queryStringValues, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(int pageId, string queryString) - { - return new RedirectToUmbracoPageResult(pageId, queryString, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the Umbraco page with the given id - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid key) - { - return new RedirectToUmbracoPageResult(key); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid key, NameValueCollection queryStringValues) - { - return new RedirectToUmbracoPageResult(key, queryStringValues); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(Guid key, string queryString) - { - return new RedirectToUmbracoPageResult(key, queryString); - } - - /// - /// Redirects to the Umbraco page with the given id - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent) - { - return new RedirectToUmbracoPageResult(publishedContent, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent, NameValueCollection queryStringValues) - { - return new RedirectToUmbracoPageResult(publishedContent, queryStringValues, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the Umbraco page with the given id and passes provided querystring - /// - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToUmbracoPage(IPublishedContent publishedContent, string queryString) - { - return new RedirectToUmbracoPageResult(publishedContent, queryString, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the currently rendered Umbraco page - /// - /// - protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage() - { - return new RedirectToUmbracoPageResult(CurrentPage, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the currently rendered Umbraco page and passes provided querystring - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(NameValueCollection queryStringValues) - { - return new RedirectToUmbracoPageResult(CurrentPage, queryStringValues, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the currently rendered Umbraco page and passes provided querystring - /// - /// - /// - protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(string queryString) - { - return new RedirectToUmbracoPageResult(CurrentPage, queryString, Current.PublishedUrlProvider); - } - - /// - /// Redirects to the currently rendered Umbraco URL - /// - /// - /// - /// this is useful if you need to redirect - /// to the current page but the current page is actually a rewritten URL normally done with something like - /// Server.Transfer. - /// - protected RedirectToUmbracoUrlResult RedirectToCurrentUmbracoUrl() - { - return new RedirectToUmbracoUrlResult(UmbracoContext); - } - - /// - /// Returns the currently rendered Umbraco page - /// - /// - protected UmbracoPageResult CurrentUmbracoPage() - { - return new UmbracoPageResult(ProfilingLogger); - } - - /// - /// Gets the current page. - /// - protected virtual IPublishedContent CurrentPage - { - get - { - var routeDefAttempt = TryGetRouteDefinitionFromAncestorViewContexts(); - if (routeDefAttempt.Success == false) - throw routeDefAttempt.Exception; - - var routeDef = routeDefAttempt.Result; - return routeDef.PublishedRequest.PublishedContent; - } - } - - /// - /// we need to recursively find the route definition based on the parent view context - /// - /// - /// - /// We may have Child Actions within Child actions so we need to recursively look this up. - /// see: http://issues.umbraco.org/issue/U4-1844 - /// - private Attempt TryGetRouteDefinitionFromAncestorViewContexts() - { - var currentContext = ControllerContext; - while (currentContext != null) - { - var currentRouteData = currentContext.RouteData; - if (currentRouteData.Values.ContainsKey(Core.Constants.Web.UmbracoRouteDefinitionDataToken)) - { - return Attempt.Succeed((RouteDefinition)currentRouteData.Values[Core.Constants.Web.UmbracoRouteDefinitionDataToken]); - } - - currentContext = currentContext.IsChildAction - ? currentContext.ParentActionViewContext - : null; - } - return Attempt.Fail( - new InvalidOperationException("Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request")); - } - - } } diff --git a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs deleted file mode 100644 index 580924b909..0000000000 --- a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.IO; -using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; -using Umbraco.Core.Logging; - -namespace Umbraco.Web.Mvc -{ - /// - /// Used by posted forms to proxy the result to the page in which the current URL matches on - /// - /// Migrated already to .Net Core - public class UmbracoPageResult : ActionResult - { - private readonly IProfilingLogger _profilingLogger; - - public UmbracoPageResult(IProfilingLogger profilingLogger) - { - _profilingLogger = profilingLogger; - } - - public override void ExecuteResult(ControllerContext context) - { - ResetRouteData(context.RouteData); - - ValidateRouteData(context.RouteData); - - var routeDef = (RouteDefinition)context.RouteData.Values[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken]; - - var factory = ControllerBuilder.Current.GetControllerFactory(); - context.RouteData.Values["action"] = routeDef.ActionName; - ControllerBase controller = null; - - try - { - controller = CreateController(context, factory, routeDef); - - CopyControllerData(context, controller); - - ExecuteControllerAction(context, controller); - } - finally - { - CleanupController(controller, factory); - } - } - - /// - /// Executes the controller action - /// - private void ExecuteControllerAction(ControllerContext context, IController controller) - { - using (_profilingLogger.TraceDuration("Executing Umbraco RouteDefinition controller", "Finished")) - { - controller.Execute(context.RequestContext); - } - } - - /// - /// Since we could be returning the current page from a surface controller posted values in which the routing values are changed, we - /// need to revert these values back to nothing in order for the normal page to render again. - /// - private static void ResetRouteData(RouteData routeData) - { - routeData.DataTokens["area"] = null; - routeData.DataTokens["Namespaces"] = null; - } - - /// - /// Validate that the current page execution is not being handled by the normal umbraco routing system - /// - private static void ValidateRouteData(RouteData routeData) - { - if (routeData.Values.ContainsKey(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken) == false) - { - throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name + - " in the context of an Http POST when using a SurfaceController form"); - } - } - - /// - /// Ensure ModelState, ViewData and TempData is copied across - /// - private static void CopyControllerData(ControllerContext context, ControllerBase controller) - { - controller.ViewData.ModelState.Merge(context.Controller.ViewData.ModelState); - - foreach (var d in context.Controller.ViewData) - controller.ViewData[d.Key] = d.Value; - - //We cannot simply merge the temp data because during controller execution it will attempt to 'load' temp data - // but since it has not been saved, there will be nothing to load and it will revert to nothing, so the trick is - // to Save the state of the temp data first then it will automatically be picked up. - // http://issues.umbraco.org/issue/U4-1339 - - var targetController = controller as Controller; - var sourceController = context.Controller as Controller; - if (targetController != null && sourceController != null) - { - targetController.TempDataProvider = sourceController.TempDataProvider; - targetController.TempData = sourceController.TempData; - targetController.TempData.Save(sourceController.ControllerContext, sourceController.TempDataProvider); - } - - } - - /// - /// Creates a controller using the controller factory - /// - private static ControllerBase CreateController(ControllerContext context, IControllerFactory factory, RouteDefinition routeDef) - { - var controller = factory.CreateController(context.RequestContext, routeDef.ControllerName) as ControllerBase; - - if (controller == null) - throw new InvalidOperationException("Could not create controller with name " + routeDef.ControllerName + "."); - - return controller; - } - - /// - /// Cleans up the controller by releasing it using the controller factory, and by disposing it. - /// - private static void CleanupController(IController controller, IControllerFactory factory) - { - if (controller != null) - factory.ReleaseController(controller); - - if (controller != null) - controller.DisposeIfDisposable(); - } - - private class DummyView : IView - { - public void Render(ViewContext viewContext, TextWriter writer) - { - } - } - } -} diff --git a/src/Umbraco.Web/Mvc/UmbracoRequireHttpsAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoRequireHttpsAttribute.cs deleted file mode 100644 index b88d1c0736..0000000000 --- a/src/Umbraco.Web/Mvc/UmbracoRequireHttpsAttribute.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - /// - /// If Umbraco.Core.UseHttps property in web.config is set to true, this filter will redirect any http access to https. - /// - public class UmbracoRequireHttpsAttribute : RequireHttpsAttribute - { - /// - /// If Umbraco.Core.UseHttps is true and we have a non-HTTPS request, handle redirect. - /// - /// Filter context - protected override void HandleNonHttpsRequest(AuthorizationContext filterContext) - { - // If Umbraco.Core.UseHttps is set, let base method handle redirect. Otherwise, we don't care. - if (/*Current.Configs.Global().UseHttps*/ false) - { - base.HandleNonHttpsRequest(filterContext); - } - } - - /// - /// Check to see if HTTPS is currently being used if Umbraco.Core.UseHttps is true. - /// - /// Filter context - public override void OnAuthorization(AuthorizationContext filterContext) - { - // If umbracoSSL is set, let base method handle checking for HTTPS. Otherwise, we don't care. - if (/*Current.Configs.Global().UseHttps*/ false) - { - base.OnAuthorization(filterContext); - } - } - - - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b8829a557d..5b6aa01f6d 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -180,10 +180,8 @@ - - @@ -216,7 +214,6 @@ - True True @@ -224,7 +221,6 @@ -