From c335a8dbb5fcf087e18a622880b302775c5d7d03 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Sun, 9 Feb 2020 18:53:37 +0100 Subject: [PATCH 01/14] Introduced interface on UmbracoContext --- .../PublishedContentCacheTests.cs | 2 +- .../Composing/TypeFinderTests.cs | 2 +- .../Composing/TypeLoaderTests.cs | 4 +- .../UmbracoContextCache.cs | 4 +- .../PublishedContentExtensionTests.cs | 2 +- .../PublishedContentSnapshotTestBase.cs | 2 +- .../PublishedContent/PublishedMediaTests.cs | 2 +- .../Scoping/ScopedNuCacheTests.cs | 2 +- .../Templates/HtmlImageSourceParserTests.cs | 2 +- .../Templates/HtmlLocalLinkParserTests.cs | 4 +- .../TestControllerActivatorBase.cs | 2 +- .../TestHelpers/TestObjects-Mocks.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- .../Accessors/TestUmbracoContextAccessor.cs | 4 +- .../Testing/TestingTests/MockTests.cs | 2 +- .../Web/Mvc/UmbracoViewPageTests.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- .../Editors/EditorModelEventArgs.cs | 6 +- .../UserGroupAuthorizationAttribute.cs | 2 +- .../HttpContextUmbracoContextAccessor.cs | 4 +- .../HybridUmbracoContextAccessor.cs | 4 +- src/Umbraco.Web/IUmbracoContext.cs | 135 ++++++++++++++++++ src/Umbraco.Web/IUmbracoContextAccessor.cs | 2 +- src/Umbraco.Web/IUmbracoContextFactory.cs | 6 +- .../Install/HttpInstallAuthorizeAttribute.cs | 2 +- .../Install/InstallAuthorizeAttribute.cs | 2 +- .../Macros/PartialViewMacroEngine.cs | 4 +- .../Mapping/RedirectUrlMapDefinition.cs | 2 +- .../Mvc/ControllerContextExtensions.cs | 4 +- .../EnsurePublishedContentRequestAttribute.cs | 2 +- src/Umbraco.Web/Mvc/PluginController.cs | 2 +- .../Mvc/RedirectToUmbracoUrlResult.cs | 4 +- src/Umbraco.Web/Mvc/RenderMvcController.cs | 2 +- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 6 +- .../Mvc/UmbracoAuthorizeAttribute.cs | 6 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 2 +- .../Mvc/UmbracoViewPageOfTModel.cs | 4 +- .../Mvc/UmbracoVirtualNodeByIdRouteHandler.cs | 4 +- .../UmbracoVirtualNodeByUdiRouteHandler.cs | 4 +- .../Mvc/UmbracoVirtualNodeRouteHandler.cs | 4 +- src/Umbraco.Web/PublishedContentExtensions.cs | 2 +- src/Umbraco.Web/Routing/AliasUrlProvider.cs | 4 +- .../Routing/DefaultMediaUrlProvider.cs | 2 +- src/Umbraco.Web/Routing/DefaultUrlProvider.cs | 6 +- src/Umbraco.Web/Routing/DomainUtilities.cs | 2 +- src/Umbraco.Web/Routing/IMediaUrlProvider.cs | 2 +- src/Umbraco.Web/Routing/IPublishedRouter.cs | 2 +- src/Umbraco.Web/Routing/IUrlProvider.cs | 4 +- src/Umbraco.Web/Routing/PublishedRequest.cs | 4 +- src/Umbraco.Web/Routing/PublishedRouter.cs | 2 +- .../Routing/RoutableAttemptEventArgs.cs | 2 +- .../Routing/UmbracoRequestEventArgs.cs | 4 +- src/Umbraco.Web/Routing/UrlProvider.cs | 6 +- .../Routing/UrlProviderExtensions.cs | 6 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 4 +- src/Umbraco.Web/Search/UmbracoTreeSearcher.cs | 4 +- .../Security/ExternalSignInAutoLinkOptions.cs | 6 +- .../IUmbracoBackOfficeTwoFactorOptions.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- src/Umbraco.Web/UmbracoContext.cs | 29 ++-- src/Umbraco.Web/UmbracoContextFactory.cs | 4 +- src/Umbraco.Web/UmbracoContextReference.cs | 4 +- src/Umbraco.Web/UmbracoInjectedModule.cs | 4 +- src/Umbraco.Web/UmbracoWebService.cs | 2 +- .../WebApi/UmbracoApiControllerBase.cs | 2 +- .../WebApi/UmbracoAuthorizeAttribute.cs | 6 +- 66 files changed, 252 insertions(+), 121 deletions(-) create mode 100644 src/Umbraco.Web/IUmbracoContext.cs diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 7ef4495ad2..36f0c6f6b3 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Cache.PublishedCache public class PublishContentCacheTests : BaseWebTest { private FakeHttpContextFactory _httpContextFactory; - private UmbracoContext _umbracoContext; + private IUmbracoContext _umbracoContext; private IPublishedContentCache _cache; private XmlDocument _xml; diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index 5fe4c241d6..a2ed0690e5 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Composing var typesFound = typeFinder.FindClassesWithAttribute(_assemblies); Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] - typesFound = typeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); + typesFound = typeFinder.FindClassesWithAttribute(new[] { typeof (IUmbracoContext).Assembly }); Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index 21ce6aa8f8..641d4814ec 100644 --- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Composing //typeof(TabPage).Assembly, typeof(System.Web.Mvc.ActionResult).Assembly, typeof(TypeFinder).Assembly, - typeof(UmbracoContext).Assembly, + typeof(IUmbracoContext).Assembly, typeof(CheckBoxListPropertyEditor).Assembly }); @@ -196,7 +196,7 @@ AnotherContentFinder [Test] public void Create_Cached_Plugin_File() { - var types = new[] { typeof(TypeLoader), typeof(TypeLoaderTests), typeof(UmbracoContext) }; + var types = new[] { typeof(TypeLoader), typeof(TypeLoaderTests), typeof(IUmbracoContext) }; var typeList1 = new TypeLoader.TypeList(typeof(object), null); foreach (var type in types) typeList1.Add(type); diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/UmbracoContextCache.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/UmbracoContextCache.cs index 5d48e9eae3..e967a1ea12 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/UmbracoContextCache.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/UmbracoContextCache.cs @@ -6,8 +6,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache { static class UmbracoContextCache { - static readonly ConditionalWeakTable> Caches - = new ConditionalWeakTable>(); + static readonly ConditionalWeakTable> Caches + = new ConditionalWeakTable>(); public static ConcurrentDictionary Current { diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs index d1c39e1e31..fdf9863c78 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs @@ -12,7 +12,7 @@ namespace Umbraco.Tests.PublishedContent [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] public class PublishedContentExtensionTests : PublishedContentTestBase { - private UmbracoContext _ctx; + private IUmbracoContext _ctx; private string _xmlContent = ""; private bool _createContentTypes = true; private Dictionary _contentTypes; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 8698eb18d7..89995ebf73 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -56,7 +56,7 @@ namespace Umbraco.Tests.PublishedContent .ToList()); } - private UmbracoContext GetUmbracoContext() + private IUmbracoContext GetUmbracoContext() { RouteData routeData = null; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 94e85dd011..89b8de8085 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -68,7 +68,7 @@ namespace Umbraco.Tests.PublishedContent /// /// /// - internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) + internal IPublishedContent GetNode(int id, IUmbracoContext umbracoContext) { var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null, HostingEnvironment), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 9e351ff3c9..d4d00f60ef 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Scoping filePermissionHelper); } - protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) + protected IUmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) { // ensure we have a PublishedSnapshotService var service = PublishedSnapshotService as PublishedSnapshotService; diff --git a/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs b/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs index d39586890a..141a0a916d 100644 --- a/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs +++ b/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Templates var media = new Mock(); media.Setup(x => x.ContentType).Returns(mediaType); var mediaUrlProvider = new Mock(); - mediaUrlProvider.Setup(x => x.GetMediaUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + mediaUrlProvider.Setup(x => x.GetMediaUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/media/1001/my-image.jpg")); var umbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs b/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs index 17f0471252..5560e39152 100644 --- a/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs +++ b/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Templates //setup a mock url provider which we'll use for testing var contentUrlProvider = new Mock(); contentUrlProvider - .Setup(x => x.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(x => x.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/my-test-url")); var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); var publishedContent = new Mock(); @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Templates var media = new Mock(); media.Setup(x => x.ContentType).Returns(mediaType); var mediaUrlProvider = new Mock(); - mediaUrlProvider.Setup(x => x.GetMediaUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + mediaUrlProvider.Setup(x => x.GetMediaUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/media/1001/my-image.jpg")); var umbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 17e1918d05..c0279e1204 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -150,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting umbracoContextAccessor.UmbracoContext = umbCtx; var urlHelper = new Mock(); - urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/hello/world/1234")); var membershipHelper = new MembershipHelper(umbCtx.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), new MockShortStringHelper(), Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 7230d1101e..70c3707b04 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -109,7 +109,7 @@ namespace Umbraco.Tests.TestHelpers /// /// An Umbraco context. /// This should be the minimum Umbraco context. - public UmbracoContext GetUmbracoContextMock(IUmbracoContextAccessor accessor = null) + public IUmbracoContext GetUmbracoContextMock(IUmbracoContextAccessor accessor = null) { var httpContext = Mock.Of(); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 86442d89c0..faeb5b10ec 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -357,7 +357,7 @@ namespace Umbraco.Tests.TestHelpers } } - protected UmbracoContext GetUmbracoContext(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null, IEnumerable mediaUrlProviders = null, IGlobalSettings globalSettings = null, IPublishedSnapshotService snapshotService = null) + protected IUmbracoContext GetUmbracoContext(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null, IEnumerable mediaUrlProviders = null, IGlobalSettings globalSettings = null, IPublishedSnapshotService snapshotService = null) { // ensure we have a PublishedCachesService var service = snapshotService ?? PublishedSnapshotService as XmlPublishedSnapshotService; diff --git a/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs b/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs index 4f3b801af9..f9862701ea 100644 --- a/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs +++ b/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs @@ -4,13 +4,13 @@ namespace Umbraco.Tests.Testing.Objects.Accessors { public class TestUmbracoContextAccessor : IUmbracoContextAccessor { - public UmbracoContext UmbracoContext { get; set; } + public IUmbracoContext UmbracoContext { get; set; } public TestUmbracoContextAccessor() { } - public TestUmbracoContextAccessor(UmbracoContext umbracoContext) + public TestUmbracoContextAccessor(IUmbracoContext umbracoContext) { UmbracoContext = umbracoContext; } diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 6f807f62c5..724eb29266 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Testing.TestingTests var umbracoContext = TestObjects.GetUmbracoContextMock(); var urlProviderMock = new Mock(); - urlProviderMock.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + urlProviderMock.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/hello/world/1234")); var urlProvider = urlProviderMock.Object; diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index adc0cbe770..c99d2cd943 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -404,7 +404,7 @@ namespace Umbraco.Tests.Web.Mvc return context; } - protected UmbracoContext GetUmbracoContext(ILogger logger, IUmbracoSettingsSection umbracoSettings, string url, int templateId, RouteData routeData = null, bool setSingleton = false) + protected IUmbracoContext GetUmbracoContext(ILogger logger, IUmbracoSettingsSection umbracoSettings, string url, int templateId, RouteData routeData = null, bool setSingleton = false) { var svcCtx = GetServiceContext(); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index bd2326b35a..f9b0edb49a 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -108,7 +108,7 @@ namespace Umbraco.Web.Composing #region Web Getters - public static UmbracoContext UmbracoContext + public static IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; public static UmbracoHelper UmbracoHelper diff --git a/src/Umbraco.Web/Editors/EditorModelEventArgs.cs b/src/Umbraco.Web/Editors/EditorModelEventArgs.cs index daf262fce5..24ee1a3d85 100644 --- a/src/Umbraco.Web/Editors/EditorModelEventArgs.cs +++ b/src/Umbraco.Web/Editors/EditorModelEventArgs.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.Editors Model = (T)baseArgs.Model; } - public EditorModelEventArgs(T model, UmbracoContext umbracoContext) + public EditorModelEventArgs(T model, IUmbracoContext umbracoContext) : base(model, umbracoContext) { Model = model; @@ -34,13 +34,13 @@ namespace Umbraco.Web.Editors public class EditorModelEventArgs : EventArgs { - public EditorModelEventArgs(object model, UmbracoContext umbracoContext) + public EditorModelEventArgs(object model, IUmbracoContext umbracoContext) { Model = model; UmbracoContext = umbracoContext; } public object Model { get; set; } - public UmbracoContext UmbracoContext { get; } + public IUmbracoContext UmbracoContext { get; } } } diff --git a/src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs b/src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs index 454d81666a..daa3ae3491 100644 --- a/src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs +++ b/src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.Editors.Filters _paramName = paramName; } - private UmbracoContext GetUmbracoContext() + private IUmbracoContext GetUmbracoContext() { return _umbracoContextAccessor?.UmbracoContext ?? Composing.Current.UmbracoContext; } diff --git a/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs b/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs index 5a05ee85ff..a6f89ec154 100644 --- a/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs @@ -12,13 +12,13 @@ namespace Umbraco.Web _httpContextAccessor = httpContextAccessor; } - public UmbracoContext UmbracoContext + public IUmbracoContext UmbracoContext { get { var httpContext = _httpContextAccessor.HttpContext; if (httpContext == null) throw new Exception("oops:httpContext"); - return (UmbracoContext) httpContext.Items[HttpContextItemKey]; + return (IUmbracoContext) httpContext.Items[HttpContextItemKey]; } set diff --git a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs index d5d03d58bb..3c22826f30 100644 --- a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs @@ -3,7 +3,7 @@ /// /// Implements a hybrid . /// - internal class HybridUmbracoContextAccessor : HybridAccessorBase, IUmbracoContextAccessor + internal class HybridUmbracoContextAccessor : HybridAccessorBase, IUmbracoContextAccessor { /// /// Initializes a new instance of the class. @@ -18,7 +18,7 @@ /// /// Gets or sets the object. /// - public UmbracoContext UmbracoContext + public IUmbracoContext UmbracoContext { get => Value; set => Value = value; diff --git a/src/Umbraco.Web/IUmbracoContext.cs b/src/Umbraco.Web/IUmbracoContext.cs new file mode 100644 index 0000000000..8a624a8132 --- /dev/null +++ b/src/Umbraco.Web/IUmbracoContext.cs @@ -0,0 +1,135 @@ +using System; +using System.Web; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Web.PublishedCache; +using Umbraco.Web.Routing; +using Umbraco.Web.Security; + +namespace Umbraco.Web +{ + public interface IUmbracoContext + { + /// + /// This is used internally for performance calculations, the ObjectCreated DateTime is set as soon as this + /// object is instantiated which in the web site is created during the BeginRequest phase. + /// We can then determine complete rendering time from that. + /// + DateTime ObjectCreated { get; } + + /// + /// This is used internally for debugging and also used to define anything required to distinguish this request from another. + /// + Guid UmbracoRequestId { get; } + + /// + /// Gets the WebSecurity class + /// + WebSecurity Security { get; } + + /// + /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. + /// + Uri OriginalRequestUrl { get; } + + /// + /// Gets the cleaned up url that is handled by Umbraco. + /// + /// That is, lowercase, no trailing slash after path, no .aspx... + Uri CleanedUmbracoUrl { get; } + + /// + /// Gets the published snapshot. + /// + IPublishedSnapshot PublishedSnapshot { get; } + + /// + /// Gets the published content cache. + /// + IPublishedContentCache Content { get; } + + /// + /// Gets the published media cache. + /// + IPublishedMediaCache Media { get; } + + /// + /// Gets the domains cache. + /// + IDomainCache Domains { get; } + + /// + /// Boolean value indicating whether the current request is a front-end umbraco request + /// + bool IsFrontEndUmbracoRequest { get; } + + /// + /// Gets the url provider. + /// + UrlProvider UrlProvider { get; } + + /// + /// Gets/sets the PublishedRequest object + /// + PublishedRequest PublishedRequest { get; set; } + + /// + /// Exposes the HttpContext for the current request + /// + HttpContextBase HttpContext { get; } + + /// + /// Gets the variation context accessor. + /// + IVariationContextAccessor VariationContextAccessor { get; } + + /// + /// Gets a value indicating whether the request has debugging enabled + /// + /// true if this instance is debug; otherwise, false. + bool IsDebug { get; } + + /// + /// Determines whether the current user is in a preview mode and browsing the site (ie. not in the admin UI) + /// + bool InPreviewMode { get; } + + string PreviewToken { get; } + + /// + /// Gets the url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The url for the content. + string Url(int contentId, string culture = null); + + /// + /// Gets the url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The url for the content. + string Url(Guid contentId, string culture = null); + + /// + /// Gets the url of a content identified by its identifier, in a specified mode. + /// + /// The content identifier. + /// The mode. + /// + /// The url for the content. + string Url(int contentId, UrlMode mode, string culture = null); + + /// + /// Gets the url of a content identified by its identifier, in a specified mode. + /// + /// The content identifier. + /// The mode. + /// + /// The url for the content. + string Url(Guid contentId, UrlMode mode, string culture = null); + + IDisposable ForcedPreview(bool preview); + void Dispose(); + } +} diff --git a/src/Umbraco.Web/IUmbracoContextAccessor.cs b/src/Umbraco.Web/IUmbracoContextAccessor.cs index 74df940865..5c7549bff6 100644 --- a/src/Umbraco.Web/IUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/IUmbracoContextAccessor.cs @@ -5,6 +5,6 @@ /// public interface IUmbracoContextAccessor { - UmbracoContext UmbracoContext { get; set; } + IUmbracoContext UmbracoContext { get; set; } } } diff --git a/src/Umbraco.Web/IUmbracoContextFactory.cs b/src/Umbraco.Web/IUmbracoContextFactory.cs index 6d89578da7..37e7fa0880 100644 --- a/src/Umbraco.Web/IUmbracoContextFactory.cs +++ b/src/Umbraco.Web/IUmbracoContextFactory.cs @@ -3,15 +3,15 @@ namespace Umbraco.Web { /// - /// Creates and manages instances. + /// Creates and manages instances. /// public interface IUmbracoContextFactory { /// - /// Ensures that a current exists. + /// Ensures that a current exists. /// /// - /// If an is already registered in the + /// If an is already registered in the /// , returns a non-root reference to it. /// Otherwise, create a new instance, registers it, and return a root reference /// to it. diff --git a/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs b/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs index 4cf844669f..ad02f1248d 100644 --- a/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Install private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS diff --git a/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs b/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs index da2f2bab57..df6802bd51 100644 --- a/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Install private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs index 44ee77507b..ecfda80399 100644 --- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Macros public class PartialViewMacroEngine { private readonly Func _getHttpContext; - private readonly Func _getUmbracoContext; + private readonly Func _getUmbracoContext; public PartialViewMacroEngine() { @@ -40,7 +40,7 @@ namespace Umbraco.Web.Macros /// /// /// - internal PartialViewMacroEngine(HttpContextBase httpContext, UmbracoContext umbracoContext) + internal PartialViewMacroEngine(HttpContextBase httpContext, IUmbracoContext umbracoContext) { _getHttpContext = () => httpContext; _getUmbracoContext = () => umbracoContext; diff --git a/src/Umbraco.Web/Models/Mapping/RedirectUrlMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/RedirectUrlMapDefinition.cs index e773fcfee5..c7d65ed56d 100644 --- a/src/Umbraco.Web/Models/Mapping/RedirectUrlMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/RedirectUrlMapDefinition.cs @@ -13,7 +13,7 @@ namespace Umbraco.Web.Models.Mapping _umbracoContextAccessor = umbracoContextAccessor; } - private UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; public void DefineMaps(UmbracoMapper mapper) { diff --git a/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs b/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs index 393b6882c9..4baaaac4fc 100644 --- a/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs +++ b/src/Umbraco.Web/Mvc/ControllerContextExtensions.cs @@ -10,10 +10,10 @@ namespace Umbraco.Web.Mvc /// /// The controller context. /// The Umbraco context. - public static UmbracoContext GetUmbracoContext(this ControllerContext controllerContext) + public static IUmbracoContext GetUmbracoContext(this ControllerContext controllerContext) { var o = controllerContext.GetDataTokenInViewContextHierarchy(Core.Constants.Web.UmbracoContextDataToken); - return o != null ? o as UmbracoContext : Current.UmbracoContext; + return o != null ? o as IUmbracoContext : Current.UmbracoContext; } /// diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 187c64d93a..31a3d6a9ea 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -69,7 +69,7 @@ namespace Umbraco.Web.Mvc /// /// Exposes the UmbracoContext /// - protected UmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; + protected IUmbracoContext UmbracoContext => _umbracoContextAccessor?.UmbracoContext ?? Current.UmbracoContext; // TODO: try lazy property injection? private IPublishedRouter PublishedRouter => Current.Factory.GetInstance(); diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 9e080ee042..a87f495c9b 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; + public virtual IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; /// /// Gets the database context accessor. diff --git a/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs b/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs index ddc989eb57..3690e98790 100644 --- a/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs +++ b/src/Umbraco.Web/Mvc/RedirectToUmbracoUrlResult.cs @@ -13,13 +13,13 @@ namespace Umbraco.Web.Mvc /// public class RedirectToUmbracoUrlResult : ActionResult { - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; /// /// Creates a new RedirectToUmbracoResult /// /// - public RedirectToUmbracoUrlResult(UmbracoContext umbracoContext) + public RedirectToUmbracoUrlResult(IUmbracoContext umbracoContext) { _umbracoContext = umbracoContext; } diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 64c9ad52c4..4d191d8f30 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the Umbraco context. /// - public override UmbracoContext UmbracoContext => PublishedRequest.UmbracoContext; //TODO: Why? + public override IUmbracoContext UmbracoContext => PublishedRequest.UmbracoContext; //TODO: Why? /// /// Gets the current content item. diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index fdf38e78b3..186c9f212a 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -29,7 +29,7 @@ namespace Umbraco.Web.Mvc private readonly IControllerFactory _controllerFactory; private readonly IShortStringHelper _shortStringHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; public RenderRouteHandler(IUmbracoContextAccessor umbracoContextAccessor, IControllerFactory controllerFactory, IShortStringHelper shortStringHelper) { @@ -38,14 +38,14 @@ namespace Umbraco.Web.Mvc _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); } - public RenderRouteHandler(UmbracoContext umbracoContext, IControllerFactory controllerFactory, IShortStringHelper 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 UmbracoContext UmbracoContext => _umbracoContext ?? _umbracoContextAccessor.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContext ?? _umbracoContextAccessor.UmbracoContext; private UmbracoFeatures Features => Current.Factory.GetInstance(); // TODO: inject diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index fa0b1c5458..0c6898553c 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -13,20 +13,20 @@ namespace Umbraco.Web.Mvc public sealed class UmbracoAuthorizeAttribute : AuthorizeAttribute { // see note in HttpInstallAuthorizeAttribute - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; private readonly IRuntimeState _runtimeState; private readonly string _redirectUrl; private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// /// /// - public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) + public UmbracoAuthorizeAttribute(IUmbracoContext umbracoContext, IRuntimeState runtimeState) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 6841bf5875..3056a9837a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; + public virtual IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; /// /// Gets or sets the Umbraco context accessor. diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 97a8eaf294..6e01f76abe 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Mvc private readonly IGlobalSettings _globalSettings; private readonly IUmbracoSettingsSection _umbracoSettingsSection; - private UmbracoContext _umbracoContext; + private IUmbracoContext _umbracoContext; private UmbracoHelper _helper; /// @@ -50,7 +50,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the Umbraco context. /// - public UmbracoContext UmbracoContext => _umbracoContext + public IUmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = ViewContext.GetUmbracoContext() ?? Current.UmbracoContext); /// diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByIdRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByIdRouteHandler.cs index 0ada310b12..ae38bb945d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByIdRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByIdRouteHandler.cs @@ -12,13 +12,13 @@ namespace Umbraco.Web.Mvc _realNodeId = realNodeId; } - protected sealed override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext) + protected sealed override IPublishedContent FindContent(RequestContext requestContext, IUmbracoContext umbracoContext) { var byId = umbracoContext.Content.GetById(_realNodeId); return byId == null ? null : FindContent(requestContext, umbracoContext, byId); } - protected virtual IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext, IPublishedContent baseContent) + protected virtual IPublishedContent FindContent(RequestContext requestContext, IUmbracoContext umbracoContext, IPublishedContent baseContent) { return baseContent; } diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByUdiRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByUdiRouteHandler.cs index a1ee6c732a..7aee823b9a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByUdiRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByUdiRouteHandler.cs @@ -13,13 +13,13 @@ namespace Umbraco.Web.Mvc _realNodeUdi = realNodeUdi; } - protected sealed override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext) + protected sealed override IPublishedContent FindContent(RequestContext requestContext, IUmbracoContext umbracoContext) { var byId = umbracoContext.Content.GetById(_realNodeUdi); return byId == null ? null : FindContent(requestContext, umbracoContext, byId); } - protected virtual IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext, IPublishedContent baseContent) + protected virtual IPublishedContent FindContent(RequestContext requestContext, IUmbracoContext umbracoContext, IPublishedContent baseContent) { return baseContent; } diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index 8fc8b255a8..9d6b336265 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.Mvc /// ]]> /// /// - protected virtual UmbracoContext GetUmbracoContext(RequestContext requestContext) + protected virtual IUmbracoContext GetUmbracoContext(RequestContext requestContext) { return Composing.Current.UmbracoContext; } @@ -88,7 +88,7 @@ namespace Umbraco.Web.Mvc return new MvcHandler(requestContext); } - protected abstract IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext); + protected abstract IPublishedContent FindContent(RequestContext requestContext, IUmbracoContext umbracoContext); protected virtual void PreparePublishedContentRequest(PublishedRequest request) { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 11e8bd9f64..e4d2524c80 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web // private static IPublishedValueFallback PublishedValueFallback => Current.PublishedValueFallback; private static IPublishedSnapshot PublishedSnapshot => Current.PublishedSnapshot; - private static UmbracoContext UmbracoContext => Current.UmbracoContext; + private static IUmbracoContext UmbracoContext => Current.UmbracoContext; private static ISiteDomainHelper SiteDomainHelper => Current.Factory.GetInstance(); private static IVariationContextAccessor VariationContextAccessor => Current.VariationContextAccessor; private static IExamineManager ExamineManager => Current.Factory.GetInstance(); diff --git a/src/Umbraco.Web/Routing/AliasUrlProvider.cs b/src/Umbraco.Web/Routing/AliasUrlProvider.cs index f84ac608d2..849a85dd2c 100644 --- a/src/Umbraco.Web/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Web/Routing/AliasUrlProvider.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Routing #region GetUrl /// - public UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current) + public UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current) { return null; // we have nothing to say } @@ -51,7 +51,7 @@ namespace Umbraco.Web.Routing /// Other urls are those that GetUrl would not return in the current context, but would be valid /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...). /// - public IEnumerable GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current) + public IEnumerable GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current) { var node = umbracoContext.Content.GetById(id); if (node == null) diff --git a/src/Umbraco.Web/Routing/DefaultMediaUrlProvider.cs b/src/Umbraco.Web/Routing/DefaultMediaUrlProvider.cs index beaf5f5864..c7c987e0e5 100644 --- a/src/Umbraco.Web/Routing/DefaultMediaUrlProvider.cs +++ b/src/Umbraco.Web/Routing/DefaultMediaUrlProvider.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing } /// - public virtual UrlInfo GetMediaUrl(UmbracoContext umbracoContext, IPublishedContent content, + public virtual UrlInfo GetMediaUrl(IUmbracoContext umbracoContext, IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current) { var prop = content.GetProperty(propertyAlias); diff --git a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs index 4092538481..43d4d5dd90 100644 --- a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs @@ -29,7 +29,7 @@ namespace Umbraco.Web.Routing #region GetUrl /// - public virtual UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current) + public virtual UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current) { if (!current.IsAbsoluteUri) throw new ArgumentException("Current url must be absolute.", nameof(current)); @@ -39,7 +39,7 @@ namespace Umbraco.Web.Routing return GetUrlFromRoute(route, umbracoContext, content.Id, current, mode, culture); } - internal UrlInfo GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlMode mode, string culture) + internal UrlInfo GetUrlFromRoute(string route, IUmbracoContext umbracoContext, int id, Uri current, UrlMode mode, string culture) { if (string.IsNullOrWhiteSpace(route)) { @@ -76,7 +76,7 @@ namespace Umbraco.Web.Routing /// Other urls are those that GetUrl would not return in the current context, but would be valid /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...). /// - public virtual IEnumerable GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current) + public virtual IEnumerable GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current) { var node = umbracoContext.Content.GetById(id); if (node == null) diff --git a/src/Umbraco.Web/Routing/DomainUtilities.cs b/src/Umbraco.Web/Routing/DomainUtilities.cs index fb0c56b28d..9255ee46ef 100644 --- a/src/Umbraco.Web/Routing/DomainUtilities.cs +++ b/src/Umbraco.Web/Routing/DomainUtilities.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Routing /// one document per culture), and domains, withing the context of a current Uri, assign /// a culture to that document. /// - internal static string GetCultureFromDomains(int contentId, string contentPath, Uri current, UmbracoContext umbracoContext, ISiteDomainHelper siteDomainHelper) + internal static string GetCultureFromDomains(int contentId, string contentPath, Uri current, IUmbracoContext umbracoContext, ISiteDomainHelper siteDomainHelper) { if (umbracoContext == null) throw new InvalidOperationException("A current UmbracoContext is required."); diff --git a/src/Umbraco.Web/Routing/IMediaUrlProvider.cs b/src/Umbraco.Web/Routing/IMediaUrlProvider.cs index 8a81b27415..0c128057f1 100644 --- a/src/Umbraco.Web/Routing/IMediaUrlProvider.cs +++ b/src/Umbraco.Web/Routing/IMediaUrlProvider.cs @@ -26,6 +26,6 @@ namespace Umbraco.Web.Routing /// e.g. a cdn url provider will most likely always return an absolute url. /// If the provider is unable to provide a url, it returns null. /// - UrlInfo GetMediaUrl(UmbracoContext umbracoContext, IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current); + UrlInfo GetMediaUrl(IUmbracoContext umbracoContext, IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current); } } diff --git a/src/Umbraco.Web/Routing/IPublishedRouter.cs b/src/Umbraco.Web/Routing/IPublishedRouter.cs index df06e42e55..77502612c3 100644 --- a/src/Umbraco.Web/Routing/IPublishedRouter.cs +++ b/src/Umbraco.Web/Routing/IPublishedRouter.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.Routing /// The current Umbraco context. /// The (optional) request Uri. /// A published request. - PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null); + PublishedRequest CreateRequest(IUmbracoContext umbracoContext, Uri uri = null); /// /// Prepares a request for rendering. diff --git a/src/Umbraco.Web/Routing/IUrlProvider.cs b/src/Umbraco.Web/Routing/IUrlProvider.cs index c0ce1fef39..16c1a1c91c 100644 --- a/src/Umbraco.Web/Routing/IUrlProvider.cs +++ b/src/Umbraco.Web/Routing/IUrlProvider.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Routing /// when no culture is specified, the current culture. /// If the provider is unable to provide a url, it should return null. /// - UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current); + UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current); /// /// Gets the other urls of a published content. @@ -37,6 +37,6 @@ namespace Umbraco.Web.Routing /// Other urls are those that GetUrl would not return in the current context, but would be valid /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...). /// - IEnumerable GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current); + IEnumerable GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current); } } diff --git a/src/Umbraco.Web/Routing/PublishedRequest.cs b/src/Umbraco.Web/Routing/PublishedRequest.cs index 37a58ad375..becdbc8d27 100644 --- a/src/Umbraco.Web/Routing/PublishedRequest.cs +++ b/src/Umbraco.Web/Routing/PublishedRequest.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Routing /// The published router. /// The Umbraco context. /// The request Uri. - internal PublishedRequest(IPublishedRouter publishedRouter, UmbracoContext umbracoContext, IUmbracoSettingsSection umbracoSettingsSection, Uri uri = null) + internal PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IUmbracoSettingsSection umbracoSettingsSection, Uri uri = null) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); @@ -48,7 +48,7 @@ namespace Umbraco.Web.Routing /// /// Gets the UmbracoContext. /// - public UmbracoContext UmbracoContext { get; } + public IUmbracoContext UmbracoContext { get; } /// /// Gets or sets the cleaned up Uri used for routing. diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 9148ce2e31..82041f04fa 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -55,7 +55,7 @@ namespace Umbraco.Web.Routing } /// - public PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null) + public PublishedRequest CreateRequest(IUmbracoContext umbracoContext, Uri uri = null) { return new PublishedRequest(this, umbracoContext, _umbracoSettingsSection, uri ?? umbracoContext.CleanedUmbracoUrl); } diff --git a/src/Umbraco.Web/Routing/RoutableAttemptEventArgs.cs b/src/Umbraco.Web/Routing/RoutableAttemptEventArgs.cs index 96b377b103..eea33f95fe 100644 --- a/src/Umbraco.Web/Routing/RoutableAttemptEventArgs.cs +++ b/src/Umbraco.Web/Routing/RoutableAttemptEventArgs.cs @@ -9,7 +9,7 @@ namespace Umbraco.Web.Routing { public EnsureRoutableOutcome Outcome { get; private set; } - public RoutableAttemptEventArgs(EnsureRoutableOutcome reason, UmbracoContext umbracoContext, HttpContextBase httpContext) + public RoutableAttemptEventArgs(EnsureRoutableOutcome reason, IUmbracoContext umbracoContext, HttpContextBase httpContext) : base(umbracoContext, httpContext) { Outcome = reason; diff --git a/src/Umbraco.Web/Routing/UmbracoRequestEventArgs.cs b/src/Umbraco.Web/Routing/UmbracoRequestEventArgs.cs index 5b2be178fd..56c9c9f07d 100644 --- a/src/Umbraco.Web/Routing/UmbracoRequestEventArgs.cs +++ b/src/Umbraco.Web/Routing/UmbracoRequestEventArgs.cs @@ -8,10 +8,10 @@ namespace Umbraco.Web.Routing /// public class UmbracoRequestEventArgs : EventArgs { - public UmbracoContext UmbracoContext { get; private set; } + public IUmbracoContext UmbracoContext { get; private set; } public HttpContextBase HttpContext { get; private set; } - public UmbracoRequestEventArgs(UmbracoContext umbracoContext, HttpContextBase httpContext) + public UmbracoRequestEventArgs(IUmbracoContext umbracoContext, HttpContextBase httpContext) { UmbracoContext = umbracoContext; HttpContext = httpContext; diff --git a/src/Umbraco.Web/Routing/UrlProvider.cs b/src/Umbraco.Web/Routing/UrlProvider.cs index d42639b781..8720d4c52a 100644 --- a/src/Umbraco.Web/Routing/UrlProvider.cs +++ b/src/Umbraco.Web/Routing/UrlProvider.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Routing /// The list of url providers. /// The list of media url providers. /// The current variation accessor. - public UrlProvider(UmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders, IEnumerable mediaUrlProviders, IVariationContextAccessor variationContextAccessor) + public UrlProvider(IUmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders, IEnumerable mediaUrlProviders, IVariationContextAccessor variationContextAccessor) { if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings)); @@ -48,7 +48,7 @@ namespace Umbraco.Web.Routing /// The list of media url providers /// The current variation accessor. /// An optional provider mode. - public UrlProvider(UmbracoContext umbracoContext, IEnumerable urlProviders, IEnumerable mediaUrlProviders, IVariationContextAccessor variationContextAccessor, UrlMode mode = UrlMode.Auto) + public UrlProvider(IUmbracoContext umbracoContext, IEnumerable urlProviders, IEnumerable mediaUrlProviders, IVariationContextAccessor variationContextAccessor, UrlMode mode = UrlMode.Auto) { _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _urlProviders = urlProviders; @@ -58,7 +58,7 @@ namespace Umbraco.Web.Routing Mode = mode; } - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; private readonly IEnumerable _urlProviders; private readonly IEnumerable _mediaUrlProviders; private readonly IVariationContextAccessor _variationContextAccessor; diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs index 9a0579daa1..e4359ad03e 100644 --- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Routing /// public static IEnumerable GetContentUrls(this IContent content, IPublishedRouter publishedRouter, - UmbracoContext umbracoContext, + IUmbracoContext umbracoContext, ILocalizationService localizationService, ILocalizedTextService textService, IContentService contentService, @@ -96,7 +96,7 @@ namespace Umbraco.Web.Routing private static IEnumerable GetContentUrlsByCulture(IContent content, IEnumerable cultures, IPublishedRouter publishedRouter, - UmbracoContext umbracoContext, + IUmbracoContext umbracoContext, IContentService contentService, ILocalizedTextService textService, IVariationContextAccessor variationContextAccessor, @@ -165,7 +165,7 @@ namespace Umbraco.Web.Routing return UrlInfo.Message(textService.Localize("content/parentCultureNotPublished", new[] {parent.Name}), culture); } - private static bool DetectCollision(IContent content, string url, string culture, UmbracoContext umbracoContext, IPublishedRouter publishedRouter, ILocalizedTextService textService, IVariationContextAccessor variationContextAccessor, out UrlInfo urlInfo) + private static bool DetectCollision(IContent content, string url, string culture, IUmbracoContext umbracoContext, IPublishedRouter publishedRouter, ILocalizedTextService textService, IVariationContextAccessor variationContextAccessor, out UrlInfo urlInfo) { // test for collisions on the 'main' url var uri = new Uri(url.TrimEnd('/'), UriKind.RelativeOrAbsolute); diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index be551181c4..c06d8e3777 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -81,7 +81,7 @@ namespace Umbraco.Web.Runtime composition.Register(factory => MembershipProviderExtensions.GetMembersMembershipProvider()); composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); composition.Register(Lifetime.Request); - composition.Register(factory => factory.GetInstance().PublishedSnapshot.Members); + composition.Register(factory => factory.GetInstance().PublishedSnapshot.Members); // register accessors for cultures composition.RegisterUnique(); @@ -131,7 +131,7 @@ namespace Umbraco.Web.Runtime if (composition.RuntimeState.Level == RuntimeLevel.Run) composition.Register(factory => { - var umbCtx = factory.GetInstance(); + var umbCtx = factory.GetInstance(); return new UmbracoHelper(umbCtx.IsFrontEndUmbracoRequest ? umbCtx.PublishedRequest?.PublishedContent : null, factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index 0f52384409..a905320cc5 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Search /// public class UmbracoTreeSearcher { - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; private readonly ILocalizationService _languageService; private readonly IEntityService _entityService; private readonly UmbracoMapper _mapper; @@ -28,7 +28,7 @@ namespace Umbraco.Web.Search private readonly IBackOfficeExamineSearcher _backOfficeExamineSearcher; - public UmbracoTreeSearcher(UmbracoContext umbracoContext, + public UmbracoTreeSearcher(IUmbracoContext umbracoContext, ILocalizationService languageService, IEntityService entityService, UmbracoMapper mapper, diff --git a/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs b/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs index 56773293da..283f6b6b99 100644 --- a/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs +++ b/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Security /// /// /// - public string[] GetDefaultUserGroups(UmbracoContext umbracoContext, ExternalLoginInfo loginInfo) + public string[] GetDefaultUserGroups(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo) { return _defaultUserGroups; } @@ -61,7 +61,7 @@ namespace Umbraco.Web.Security /// /// For public auth providers this should always be false!!! /// - public bool ShouldAutoLinkExternalAccount(UmbracoContext umbracoContext, ExternalLoginInfo loginInfo) + public bool ShouldAutoLinkExternalAccount(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo) { return _autoLinkExternalAccount; } @@ -71,7 +71,7 @@ namespace Umbraco.Web.Security /// /// The default Culture to use for auto-linking users /// - public string GetDefaultCulture(UmbracoContext umbracoContext, ExternalLoginInfo loginInfo) + public string GetDefaultCulture(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo) { return _defaultCulture; } diff --git a/src/Umbraco.Web/Security/IUmbracoBackOfficeTwoFactorOptions.cs b/src/Umbraco.Web/Security/IUmbracoBackOfficeTwoFactorOptions.cs index acd49ec5e0..0b43342594 100644 --- a/src/Umbraco.Web/Security/IUmbracoBackOfficeTwoFactorOptions.cs +++ b/src/Umbraco.Web/Security/IUmbracoBackOfficeTwoFactorOptions.cs @@ -7,6 +7,6 @@ namespace Umbraco.Web.Security /// public interface IUmbracoBackOfficeTwoFactorOptions { - string GetTwoFactorView(IOwinContext owinContext, UmbracoContext umbracoContext, string username); + string GetTwoFactorView(IOwinContext owinContext, IUmbracoContext umbracoContext, string username); } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3ce6c64342..6cbb4afa9a 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -246,6 +246,7 @@ + @@ -715,7 +716,7 @@ Code - + diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 3b00c67b42..374b78c333 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -1,27 +1,22 @@ using System; using System.Collections.Generic; -using System.IO; using System.Web; -using System.Web.Routing; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web; +using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; namespace Umbraco.Web { - /// /// Class that encapsulates Umbraco information of a specific HTTP request /// - public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd + public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd, IUmbracoContext { private readonly IGlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; @@ -88,12 +83,12 @@ namespace Umbraco.Web /// object is instantiated which in the web site is created during the BeginRequest phase. /// We can then determine complete rendering time from that. /// - internal DateTime ObjectCreated { get; } + public DateTime ObjectCreated { get; } /// /// This is used internally for debugging and also used to define anything required to distinguish this request from another. /// - internal Guid UmbracoRequestId { get; } + public Guid UmbracoRequestId { get; } /// /// Gets the WebSecurity class @@ -103,13 +98,13 @@ namespace Umbraco.Web /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. /// - internal Uri OriginalRequestUrl { get; } + public Uri OriginalRequestUrl { get; } /// /// Gets the cleaned up url that is handled by Umbraco. /// /// That is, lowercase, no trailing slash after path, no .aspx... - internal Uri CleanedUmbracoUrl { get; } + public Uri CleanedUmbracoUrl { get; } /// /// Gets the published snapshot. @@ -167,10 +162,10 @@ namespace Umbraco.Web var request = GetRequestFromContext(); //NOTE: the request can be null during app startup! return Current.RuntimeState.Debug - && request != null - && (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false - || string.IsNullOrEmpty(request["umbdebug"]) == false - || string.IsNullOrEmpty(request.Cookies["UMB-DEBUG"]?.Value) == false); + && request != null + && (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false + || string.IsNullOrEmpty(request["umbdebug"]) == false + || string.IsNullOrEmpty(request.Cookies["UMB-DEBUG"]?.Value) == false); } } @@ -237,7 +232,7 @@ namespace Umbraco.Web #endregion - private string PreviewToken + public string PreviewToken { get { @@ -263,7 +258,7 @@ namespace Umbraco.Web // say we render a macro or RTE in a give 'preview' mode that might not be the 'current' one, // then due to the way it all works at the moment, the 'current' published snapshot need to be in the proper // default 'preview' mode - somehow we have to force it. and that could be recursive. - internal IDisposable ForcedPreview(bool preview) + public IDisposable ForcedPreview(bool preview) { InPreviewMode = preview; return PublishedSnapshot.ForcedPreview(preview, orig => InPreviewMode = orig); diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs index cc618bfc82..bb6d307250 100644 --- a/src/Umbraco.Web/UmbracoContextFactory.cs +++ b/src/Umbraco.Web/UmbracoContextFactory.cs @@ -16,7 +16,7 @@ using Umbraco.Web.Security; namespace Umbraco.Web { /// - /// Creates and manages instances. + /// Creates and manages instances. /// public class UmbracoContextFactory : IUmbracoContextFactory { @@ -52,7 +52,7 @@ namespace Umbraco.Web _ioHelper = ioHelper; } - private UmbracoContext CreateUmbracoContext(HttpContextBase httpContext) + private IUmbracoContext CreateUmbracoContext(HttpContextBase httpContext) { // make sure we have a variation context if (_variationContextAccessor.VariationContext == null) diff --git a/src/Umbraco.Web/UmbracoContextReference.cs b/src/Umbraco.Web/UmbracoContextReference.cs index 6c4ac7e54a..740f972bbf 100644 --- a/src/Umbraco.Web/UmbracoContextReference.cs +++ b/src/Umbraco.Web/UmbracoContextReference.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web /// /// Initializes a new instance of the class. /// - internal UmbracoContextReference(UmbracoContext umbracoContext, bool isRoot, IUmbracoContextAccessor umbracoContextAccessor) + internal UmbracoContextReference(IUmbracoContext umbracoContext, bool isRoot, IUmbracoContextAccessor umbracoContextAccessor) { UmbracoContext = umbracoContext; IsRoot = isRoot; @@ -31,7 +31,7 @@ namespace Umbraco.Web /// /// Gets the . /// - public UmbracoContext UmbracoContext { get; } + public IUmbracoContext UmbracoContext { get; } /// /// Gets a value indicating whether the reference is a root reference. diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index f8725632ae..8b840461d5 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -155,7 +155,7 @@ namespace Umbraco.Web /// /// /// - internal Attempt EnsureUmbracoRoutablePage(UmbracoContext context, HttpContextBase httpContext) + internal Attempt EnsureUmbracoRoutablePage(IUmbracoContext context, HttpContextBase httpContext) { var uri = context.OriginalRequestUrl; @@ -230,7 +230,7 @@ namespace Umbraco.Web // ensures Umbraco has at least one published node // if not, rewrites to splash and return false // if yes, return true - private bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext) + private bool EnsureHasContent(IUmbracoContext context, HttpContextBase httpContext) { if (context.Content.HasContent()) return true; diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index bccdb5771d..ed78314560 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web /// /// Gets the Umbraco context. /// - public UmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; + public IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; /// /// Gets the Umbraco context accessor. diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index f019ffe2df..9b35416def 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -75,7 +75,7 @@ namespace Umbraco.Web.WebApi /// /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; + public virtual IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; /// /// Gets the Umbraco context accessor. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs index 49cb75fffb..7566a4d78f 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs @@ -20,19 +20,19 @@ namespace Umbraco.Web.WebApi internal static bool Enable = true; // TODO: inject! - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContext _umbracoContext; private readonly IRuntimeState _runtimeState; private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; + private IUmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// /// /// - public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) + public UmbracoAuthorizeAttribute(IUmbracoContext umbracoContext, IRuntimeState runtimeState) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); From 2658dae6497c8b85dcb1ddcf9e636dc07aa6e536 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Sun, 9 Feb 2020 19:14:19 +0100 Subject: [PATCH 02/14] Introduced interface on WebSecurity --- .../Security/IWebSecurity.cs | 92 +++++++++++++++++++ .../Security/ValidateRequestAttempt.cs | 0 .../TestControllerActivatorBase.cs | 2 +- .../Filters/ContentSaveValidationAttribute.cs | 2 +- src/Umbraco.Web/IUmbracoContext.cs | 2 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 2 +- src/Umbraco.Web/Security/WebSecurity.cs | 8 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - src/Umbraco.Web/UmbracoContext.cs | 4 +- src/Umbraco.Web/UmbracoHttpHandler.cs | 2 +- src/Umbraco.Web/UmbracoWebService.cs | 2 +- .../WebApi/UmbracoApiControllerBase.cs | 2 +- 12 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 src/Umbraco.Abstractions/Security/IWebSecurity.cs rename src/{Umbraco.Web => Umbraco.Abstractions}/Security/ValidateRequestAttempt.cs (100%) diff --git a/src/Umbraco.Abstractions/Security/IWebSecurity.cs b/src/Umbraco.Abstractions/Security/IWebSecurity.cs new file mode 100644 index 0000000000..cc268b87b4 --- /dev/null +++ b/src/Umbraco.Abstractions/Security/IWebSecurity.cs @@ -0,0 +1,92 @@ +using Umbraco.Core; +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Web.Security +{ + public interface IWebSecurity + { + /// + /// Gets the current user. + /// + /// The current user. + IUser CurrentUser { get; } + + /// + /// Logs a user in. + /// + /// The user Id + /// returns the number of seconds until their session times out + double PerformLogin(int userId); + + /// + /// Clears the current login for the currently logged in user + /// + void ClearCurrentLogin(); + + /// + /// Validates credentials for a back office user + /// + /// + /// + /// + /// + /// This uses ASP.NET Identity to perform the validation + /// + bool ValidateBackOfficeCredentials(string username, string password); + + /// + /// Gets the current user's id. + /// + /// + Attempt GetUserId(); + + /// + /// Returns the current user's unique session id - used to mitigate csrf attacks or any other reason to validate a request + /// + /// + string GetSessionId(); + + /// + /// Validates the currently logged in user and ensures they are not timed out + /// + /// + bool ValidateCurrentUser(); + + /// + /// Validates the current user assigned to the request and ensures the stored user data is valid + /// + /// set to true if you want exceptions to be thrown if failed + /// If true requires that the user is approved to be validated + /// + ValidateRequestAttempt ValidateCurrentUser(bool throwExceptions, bool requiresApproval = true); + + /// + /// Authorizes the full request, checks for SSL and validates the current user + /// + /// set to true if you want exceptions to be thrown if failed + /// + ValidateRequestAttempt AuthorizeRequest(bool throwExceptions = false); + + /// + /// Checks if the specified user as access to the app + /// + /// + /// + /// + bool UserHasSectionAccess(string section, IUser user); + + /// + /// Checks if the specified user by username as access to the app + /// + /// + /// + /// + bool UserHasSectionAccess(string section, string username); + + /// + /// Ensures that a back office user is logged in + /// + /// + bool IsAuthenticated(); + } +} diff --git a/src/Umbraco.Web/Security/ValidateRequestAttempt.cs b/src/Umbraco.Abstractions/Security/ValidateRequestAttempt.cs similarity index 100% rename from src/Umbraco.Web/Security/ValidateRequestAttempt.cs rename to src/Umbraco.Abstractions/Security/ValidateRequestAttempt.cs diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index c0279e1204..e7abec5ee2 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -101,7 +101,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting var backofficeIdentity = (UmbracoBackOfficeIdentity) owinContext.Authentication.User.Identity; - var webSecurity = new Mock(null, null, globalSettings); + var webSecurity = new Mock(); //mock CurrentUser var groups = new List(); diff --git a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs index b94d4d43bc..de84d80074 100644 --- a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs +++ b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs @@ -83,7 +83,7 @@ namespace Umbraco.Web.Editors.Filters /// /// /// - private bool ValidateUserAccess(ContentItemSave contentItem, HttpActionContext actionContext, WebSecurity webSecurity) + private bool ValidateUserAccess(ContentItemSave contentItem, HttpActionContext actionContext, IWebSecurity webSecurity) { //We now need to validate that the user is allowed to be doing what they are doing. diff --git a/src/Umbraco.Web/IUmbracoContext.cs b/src/Umbraco.Web/IUmbracoContext.cs index 8a624a8132..a37c70dfc7 100644 --- a/src/Umbraco.Web/IUmbracoContext.cs +++ b/src/Umbraco.Web/IUmbracoContext.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web /// /// Gets the WebSecurity class /// - WebSecurity Security { get; } + IWebSecurity Security { get; } /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 3056a9837a..68605a9086 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -70,7 +70,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the web security helper. /// - public virtual WebSecurity Security => UmbracoContext.Security; + public virtual IWebSecurity Security => UmbracoContext.Security; protected UmbracoController() : this( diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 5dc6551b90..3b19fd7eb2 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Security /// /// A utility class used for dealing with USER security in Umbraco /// - public class WebSecurity + public class WebSecurity : IWebSecurity { private readonly HttpContextBase _httpContext; private readonly IUserService _userService; @@ -215,7 +215,7 @@ namespace Umbraco.Web.Security /// /// set to true if you want exceptions to be thrown if failed /// - internal ValidateRequestAttempt AuthorizeRequest(bool throwExceptions = false) + public ValidateRequestAttempt AuthorizeRequest(bool throwExceptions = false) { // check for secure connection if (_globalSettings.UseHttps && _httpContext.Request.IsSecureConnection == false) @@ -232,7 +232,7 @@ namespace Umbraco.Web.Security /// /// /// - internal virtual bool UserHasSectionAccess(string section, IUser user) + public virtual bool UserHasSectionAccess(string section, IUser user) { return user.HasSectionAccess(section); } @@ -243,7 +243,7 @@ namespace Umbraco.Web.Security /// /// /// - internal bool UserHasSectionAccess(string section, string username) + public bool UserHasSectionAccess(string section, string username) { var user = _userService.GetByUsername(username); if (user == null) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 6cbb4afa9a..5c226b257e 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -597,7 +597,6 @@ - True diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 374b78c333..5f2f43d61f 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web // warn: does *not* manage setting any IUmbracoContextAccessor internal UmbracoContext(HttpContextBase httpContext, IPublishedSnapshotService publishedSnapshotService, - WebSecurity webSecurity, + IWebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, IEnumerable urlProviders, IEnumerable mediaUrlProviders, @@ -93,7 +93,7 @@ namespace Umbraco.Web /// /// Gets the WebSecurity class /// - public WebSecurity Security { get; } + public IWebSecurity Security { get; } /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index 447bdde430..27a3255edd 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -58,7 +58,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public WebSecurity Security => UmbracoContextAccessor.UmbracoContext.Security; + public IWebSecurity Security => UmbracoContextAccessor.UmbracoContext.Security; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index ed78314560..3b35dbd6c7 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -74,7 +74,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public WebSecurity Security => UmbracoContext.Security; + public IWebSecurity Security => UmbracoContext.Security; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 9b35416def..4ac773e8c8 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -131,7 +131,7 @@ namespace Umbraco.Web.WebApi /// /// Gets the web security helper. /// - public WebSecurity Security => UmbracoContext.Security; + public IWebSecurity Security => UmbracoContext.Security; /// /// Tries to get the current HttpContext. From 794e2ccdac8b2acd1ff269ad8e866c21e6dd02f8 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Sun, 9 Feb 2020 20:20:13 +0100 Subject: [PATCH 03/14] Introduced interface on UrlProvider (Can't be named IUrlProvider) --- .../Routing/IPublishedUrlProvider.cs | 110 ++++++++++++++++++ .../Routing/UrlInfo.cs | 0 src/Umbraco.Web/IUmbracoContext.cs | 2 +- src/Umbraco.Web/Routing/UrlProvider.cs | 15 +-- src/Umbraco.Web/UmbracoContext.cs | 2 +- 5 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 src/Umbraco.Abstractions/Routing/IPublishedUrlProvider.cs rename src/{Umbraco.Infrastructure => Umbraco.Abstractions}/Routing/UrlInfo.cs (100%) diff --git a/src/Umbraco.Abstractions/Routing/IPublishedUrlProvider.cs b/src/Umbraco.Abstractions/Routing/IPublishedUrlProvider.cs new file mode 100644 index 0000000000..a26f3efaff --- /dev/null +++ b/src/Umbraco.Abstractions/Routing/IPublishedUrlProvider.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Web.Routing +{ + public interface IPublishedUrlProvider + { + /// + /// Gets or sets the provider url mode. + /// + UrlMode Mode { get; set; } + + UrlMode GetMode(bool absolute); + IPublishedContent GetDocument(int id); + IPublishedContent GetDocument(Guid id); + IPublishedContent GetMedia(Guid id); + + /// + /// Gets the url of a published content. + /// + /// The published content identifier. + /// The url mode. + /// A culture. + /// The current absolute url. + /// The url for the published content. + string GetUrl(Guid id, UrlMode mode = UrlMode.Default, string culture = null, Uri current = null); + + /// + /// Gets the url of a published content. + /// + /// The published content identifier. + /// The url mode. + /// A culture. + /// The current absolute url. + /// The url for the published content. + string GetUrl(int id, UrlMode mode = UrlMode.Default, string culture = null, Uri current = null); + + /// + /// Gets the url of a published content. + /// + /// The published content. + /// The url mode. + /// A culture. + /// The current absolute url. + /// The url for the published content. + /// + /// The url is absolute or relative depending on mode and on current. + /// If the published content is multi-lingual, gets the url for the specified culture or, + /// when no culture is specified, the current culture. + /// If the provider is unable to provide a url, it returns "#". + /// + string GetUrl(IPublishedContent content, UrlMode mode = UrlMode.Default, string culture = null, Uri current = null); + + string GetUrlFromRoute(int id, string route, string culture); + + /// + /// Gets the other urls of a published content. + /// + /// The published content id. + /// The other urls for the published content. + /// + /// Other urls are those that GetUrl would not return in the current context, but would be valid + /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...). + /// The results depend on the current url. + /// + IEnumerable GetOtherUrls(int id); + + /// + /// Gets the other urls of a published content. + /// + /// The published content id. + /// The current absolute url. + /// The other urls for the published content. + /// + /// Other urls are those that GetUrl would not return in the current context, but would be valid + /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...). + /// + IEnumerable GetOtherUrls(int id, Uri current); + + /// + /// Gets the url of a media item. + /// + /// + /// + /// + /// + /// + /// + string GetMediaUrl(Guid id, UrlMode mode = UrlMode.Default, string culture = null, string propertyAlias = Constants.Conventions.Media.File, Uri current = null); + + /// + /// Gets the url of a media item. + /// + /// The published content. + /// The property alias to resolve the url from. + /// The url mode. + /// The variation language. + /// The current absolute url. + /// The url for the media. + /// + /// The url is absolute or relative depending on mode and on current. + /// If the media is multi-lingual, gets the url for the specified culture or, + /// when no culture is specified, the current culture. + /// If the provider is unable to provide a url, it returns . + /// + string GetMediaUrl(IPublishedContent content, UrlMode mode = UrlMode.Default, string culture = null, string propertyAlias = Constants.Conventions.Media.File, Uri current = null); + } +} \ No newline at end of file diff --git a/src/Umbraco.Infrastructure/Routing/UrlInfo.cs b/src/Umbraco.Abstractions/Routing/UrlInfo.cs similarity index 100% rename from src/Umbraco.Infrastructure/Routing/UrlInfo.cs rename to src/Umbraco.Abstractions/Routing/UrlInfo.cs diff --git a/src/Umbraco.Web/IUmbracoContext.cs b/src/Umbraco.Web/IUmbracoContext.cs index a37c70dfc7..7609ad6b01 100644 --- a/src/Umbraco.Web/IUmbracoContext.cs +++ b/src/Umbraco.Web/IUmbracoContext.cs @@ -65,7 +65,7 @@ namespace Umbraco.Web /// /// Gets the url provider. /// - UrlProvider UrlProvider { get; } + IPublishedUrlProvider UrlProvider { get; } /// /// Gets/sets the PublishedRequest object diff --git a/src/Umbraco.Web/Routing/UrlProvider.cs b/src/Umbraco.Web/Routing/UrlProvider.cs index 8720d4c52a..693482db76 100644 --- a/src/Umbraco.Web/Routing/UrlProvider.cs +++ b/src/Umbraco.Web/Routing/UrlProvider.cs @@ -8,15 +8,16 @@ using Umbraco.Web.Composing; namespace Umbraco.Web.Routing { + /// /// Provides urls. /// - public class UrlProvider + public class UrlProvider : IPublishedUrlProvider { #region Ctor and configuration /// - /// Initializes a new instance of the class with an Umbraco context and a list of url providers. + /// InitialiIUrlProviderzes a new instance of the class with an Umbraco context and a list of url providers. /// /// The Umbraco context. /// Routing settings. @@ -72,10 +73,10 @@ namespace Umbraco.Web.Routing #region GetUrl - private UrlMode GetMode(bool absolute) => absolute ? UrlMode.Absolute : Mode; - private IPublishedContent GetDocument(int id) => _umbracoContext.Content.GetById(id); - private IPublishedContent GetDocument(Guid id) => _umbracoContext.Content.GetById(id); - private IPublishedContent GetMedia(Guid id) => _umbracoContext.Media.GetById(id); + public UrlMode GetMode(bool absolute) => absolute ? UrlMode.Absolute : Mode; + public IPublishedContent GetDocument(int id) => _umbracoContext.Content.GetById(id); + public IPublishedContent GetDocument(Guid id) => _umbracoContext.Content.GetById(id); + public IPublishedContent GetMedia(Guid id) => _umbracoContext.Media.GetById(id); /// /// Gets the url of a published content. @@ -138,7 +139,7 @@ namespace Umbraco.Web.Routing return url?.Text ?? "#"; // legacy wants this } - internal string GetUrlFromRoute(int id, string route, string culture) + public string GetUrlFromRoute(int id, string route, string culture) { var provider = _urlProviders.OfType().FirstOrDefault(); var url = provider == null diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 5f2f43d61f..07310e8a5c 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -134,7 +134,7 @@ namespace Umbraco.Web /// /// Gets the url provider. /// - public UrlProvider UrlProvider { get; } + public IPublishedUrlProvider UrlProvider { get; } /// /// Gets/sets the PublishedRequest object From 5784449fceb98fece8ba1a551339b917e5fbb737 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 10 Feb 2020 07:03:50 +0100 Subject: [PATCH 04/14] Started replacing UmbracoContext.HttpContext with injection of IHttpContextAccessor --- src/Umbraco.Web/Install/InstallHelper.cs | 6 +++--- src/Umbraco.Web/Macros/MacroRenderer.cs | 8 +++++--- src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs | 2 +- src/Umbraco.Web/Templates/TemplateRenderer.cs | 13 ++++++++----- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 54d1475ec6..db13ff1ed7 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -18,18 +18,18 @@ namespace Umbraco.Web.Install { private static HttpClient _httpClient; private readonly DatabaseBuilder _databaseBuilder; - private readonly HttpContextBase _httpContext; + private readonly HttpContext _httpContext; private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly IConnectionStrings _connectionStrings; private InstallationType? _installationType; - public InstallHelper(IUmbracoContextAccessor umbracoContextAccessor, + public InstallHelper(IHttpContextAccessor httpContextAccessor, DatabaseBuilder databaseBuilder, ILogger logger, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IConnectionStrings connectionStrings) { - _httpContext = umbracoContextAccessor.UmbracoContext.HttpContext; + _httpContext = httpContextAccessor.HttpContext; _logger = logger; _globalSettings = globalSettings; _umbracoVersion = umbracoVersion; diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index d331dfc65f..b64eb730c2 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -27,8 +27,9 @@ namespace Umbraco.Web.Macros private readonly AppCaches _appCaches; private readonly IMacroService _macroService; private readonly IUserService _userService; + private readonly IHttpContextAccessor _httpContextAccessor; - public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, IUserService userService) + public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, IUserService userService, IHttpContextAccessor httpContextAccessor) { _plogger = plogger ?? throw new ArgumentNullException(nameof(plogger)); _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); @@ -37,6 +38,7 @@ namespace Umbraco.Web.Macros _appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _httpContextAccessor = httpContextAccessor; } #region MacroContent cache @@ -56,7 +58,7 @@ namespace Umbraco.Web.Macros { object key = 0; - if (_umbracoContextAccessor.UmbracoContext.HttpContext?.User?.Identity?.IsAuthenticated ?? false) + if (_httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false) { //ugh, membershipproviders :( var provider = MembershipProviderExtensions.GetMembersMembershipProvider(); @@ -391,7 +393,7 @@ namespace Umbraco.Web.Macros return attributeValue; } - var context = _umbracoContextAccessor.UmbracoContext.HttpContext; + var context = _httpContextAccessor.HttpContext; foreach (var token in tokens) { diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 6e01f76abe..a8f5452ce1 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -221,7 +221,7 @@ namespace Umbraco.Web.Mvc markupToInject = string.Format(_umbracoSettingsSection.Content.PreviewBadge, Current.IOHelper.ResolveUrl(_globalSettings.UmbracoPath), - Server.UrlEncode(Current.UmbracoContext.HttpContext.Request.Url?.PathAndQuery), + Server.UrlEncode(HttpContext.Current.Request.Url?.PathAndQuery), Current.UmbracoContext.PublishedRequest.PublishedContent.Id); } else diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index b13719f6e9..4b0093f910 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -2,6 +2,7 @@ using System; using System.Globalization; using System.IO; using System.Linq; +using System.Web; using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core.Configuration.UmbracoSettings; @@ -28,8 +29,9 @@ namespace Umbraco.Web.Templates private readonly ILocalizationService _languageService; private readonly IWebRoutingSection _webRoutingSection; private readonly IShortStringHelper _shortStringHelper; + private readonly IHttpContextAccessor _httpContextAccessor; - public TemplateRenderer(IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, IWebRoutingSection webRoutingSection, IShortStringHelper shortStringHelper) + public TemplateRenderer(IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, IWebRoutingSection webRoutingSection, IShortStringHelper shortStringHelper, IHttpContextAccessor httpContextAccessor) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); @@ -37,6 +39,7 @@ namespace Umbraco.Web.Templates _languageService = textService ?? throw new ArgumentNullException(nameof(textService)); _webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection)); _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); + _httpContextAccessor = httpContextAccessor; } public void Render(int pageId, int? altTemplateId, StringWriter writer) @@ -124,7 +127,7 @@ namespace Umbraco.Web.Templates //var queryString = _umbracoContext.HttpContext.Request.QueryString.AllKeys // .ToDictionary(key => key, key => context.Request.QueryString[key]); - var requestContext = new RequestContext(_umbracoContextAccessor.UmbracoContext.HttpContext, new RouteData() + var requestContext = new RequestContext(new HttpContextWrapper(_httpContextAccessor.HttpContext), new RouteData() { Route = RouteTable.Routes["Umbraco_default"] }); @@ -172,7 +175,7 @@ namespace Umbraco.Web.Templates private void SetNewItemsOnContextObjects(PublishedRequest request) { //now, set the new ones for this page execution - _umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null; + _httpContextAccessor.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null; _umbracoContextAccessor.UmbracoContext.PublishedRequest = request; } @@ -184,7 +187,7 @@ namespace Umbraco.Web.Templates //Many objects require that these legacy items are in the http context items... before we render this template we need to first //save the values in them so that we can re-set them after we render so the rest of the execution works as per normal oldPublishedRequest = _umbracoContextAccessor.UmbracoContext.PublishedRequest; - oldAltTemplate = _umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate]; + oldAltTemplate = _httpContextAccessor.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate]; } /// @@ -193,7 +196,7 @@ namespace Umbraco.Web.Templates private void RestoreItems(PublishedRequest oldPublishedRequest, object oldAltTemplate) { _umbracoContextAccessor.UmbracoContext.PublishedRequest = oldPublishedRequest; - _umbracoContextAccessor.UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = oldAltTemplate; + _httpContextAccessor.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = oldAltTemplate; } } } From d151503dbf36cdb8e55856320ac83cad7c4fef58 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 10 Feb 2020 13:09:26 +0100 Subject: [PATCH 05/14] Started replacing UmbracoContext.HttpContext with injection of IHttpContextAccessor --- .../Routing/ContentFinderByIdTests.cs | 6 +- .../ContentFinderByPageIdQueryTests.cs | 10 +- .../Routing/RenderRouteHandlerTests.cs | 12 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 4 +- .../TestHelpers/TestObjects-Mocks.cs | 11 + .../TestHelpers/TestWithDatabaseBase.cs | 4 + .../Accessors/NoHttpContextAccessor.cs | 2 +- .../Testing/TestingTests/MockTests.cs | 5 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 4 + .../Web/Mvc/SurfaceControllerTests.cs | 6 +- .../BatchedDatabaseServerMessenger.cs | 14 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 12 +- src/Umbraco.Web/IHttpContextAccessor.cs | 2 +- src/Umbraco.Web/IUmbracoContext.cs | 5 - src/Umbraco.Web/Install/InstallHelper.cs | 2 +- .../Models/Mapping/CommonMapper.cs | 16 +- .../Net/AspNetHttpContextAccessor.cs | 4 +- .../Routing/ContentFinderByIdPath.cs | 10 +- .../Routing/ContentFinderByPageIdQuery.cs | 9 +- src/Umbraco.Web/Routing/PublishedRequest.cs | 210 +++++++++++++++++- src/Umbraco.Web/Routing/PublishedRouter.cs | 7 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Templates/TemplateRenderer.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- src/Umbraco.Web/UmbracoContextFactory.cs | 18 +- 25 files changed, 329 insertions(+), 50 deletions(-) diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 72848753e5..875117afbc 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,8 +1,10 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; +using Umbraco.Web; using Umbraco.Web.Routing; namespace Umbraco.Tests.Routing @@ -18,7 +20,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByIdPath(Factory.GetInstance().WebRouting, Logger); + var lookup = new ContentFinderByIdPath(Factory.GetInstance().WebRouting, Logger, HttpContextAccessor); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByPageIdQueryTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByPageIdQueryTests.cs index c1abb5a3a5..20bbeb92d4 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByPageIdQueryTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByPageIdQueryTests.cs @@ -1,6 +1,7 @@ using Moq; using NUnit.Framework; using Umbraco.Tests.TestHelpers; +using Umbraco.Web; using Umbraco.Web.Routing; namespace Umbraco.Tests.Routing @@ -16,15 +17,18 @@ namespace Umbraco.Tests.Routing public void Lookup_By_Page_Id(string urlAsString, int nodeMatch) { var umbracoContext = GetUmbracoContext(urlAsString); + var httpContext = GetHttpContextFactory(urlAsString).HttpContext; var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByPageIdQuery(); + var mockHttpContextAccessor = new Mock(); + mockHttpContextAccessor.Setup(x => x.HttpContext).Returns(httpContext); + var lookup = new ContentFinderByPageIdQuery(mockHttpContextAccessor.Object); //we need to manually stub the return output of HttpContext.Request["umbPageId"] - var requestMock = Mock.Get(umbracoContext.HttpContext.Request); + var requestMock = Mock.Get(httpContext.Request); requestMock.Setup(x => x["umbPageID"]) - .Returns(umbracoContext.HttpContext.Request.QueryString["umbPageID"]); + .Returns(httpContext.Request.QueryString["umbPageID"]); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 4bcb08925d..a5b5ba29a2 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -100,10 +100,12 @@ namespace Umbraco.Tests.Routing [Test] public void Umbraco_Route_Umbraco_Defined_Controller_Action() { + var url = "~/dummy-page"; var template = CreateTemplate("homePage"); var route = RouteTable.Routes["Umbraco_default"]; var routeData = new RouteData { Route = route }; - var umbracoContext = GetUmbracoContext("~/dummy-page", template.Id, routeData); + var umbracoContext = GetUmbracoContext(url, template.Id, routeData); + var httpContext = GetHttpContextFactory(url, routeData).HttpContext; var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); frequest.PublishedContent = umbracoContext.Content.GetById(1174); @@ -112,7 +114,7 @@ namespace Umbraco.Tests.Routing var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContextAccessor, Mock.Of()), ShortStringHelper); - handler.GetHandlerForRoute(umbracoContext.HttpContext.Request.RequestContext, frequest); + handler.GetHandlerForRoute(httpContext.Request.RequestContext, frequest); Assert.AreEqual("RenderMvc", routeData.Values["controller"].ToString()); //the route action will still be the one we've asked for because our RenderActionInvoker is the thing that decides // if the action matches. @@ -136,10 +138,12 @@ namespace Umbraco.Tests.Routing // could exist in the database... yet creating templates should sanitize // aliases one way or another... + var url = "~/dummy-page"; var template = CreateTemplate(templateName); var route = RouteTable.Routes["Umbraco_default"]; var routeData = new RouteData() {Route = route}; var umbracoContext = GetUmbracoContext("~/dummy-page", template.Id, routeData, true); + var httpContext = GetHttpContextFactory(url, routeData).HttpContext; var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); frequest.PublishedContent = umbracoContext.Content.GetById(1172); @@ -152,7 +156,7 @@ namespace Umbraco.Tests.Routing var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContextAccessor, Mock.Of(), context => { var membershipHelper = new MembershipHelper( - umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of()); + httpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of()); return new CustomDocumentController(Factory.GetInstance(), umbracoContextAccessor, Factory.GetInstance(), @@ -161,7 +165,7 @@ namespace Umbraco.Tests.Routing new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper)); }), ShortStringHelper); - handler.GetHandlerForRoute(umbracoContext.HttpContext.Request.RequestContext, frequest); + handler.GetHandlerForRoute(httpContext.Request.RequestContext, frequest); Assert.AreEqual("CustomDocument", routeData.Values["controller"].ToString()); Assert.AreEqual( //global::umbraco.cms.helpers.Casing.SafeAlias(template.Alias), diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 176664b467..ee922cdfcb 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Strings; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; +using Umbraco.Web; using Umbraco.Web.Composing; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Routing; @@ -102,7 +103,8 @@ namespace Umbraco.Tests.TestHelpers container?.TryGetInstance() ?? ServiceContext.CreatePartial(), new ProfilingLogger(Mock.Of(), Mock.Of()), container?.TryGetInstance() ?? Current.Factory.GetInstance(), - Mock.Of()); + Mock.Of(), + Mock.Of()); } } } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 70c3707b04..12282d1603 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -337,5 +337,16 @@ namespace Umbraco.Tests.TestHelpers } #endregion + + public IHttpContextAccessor GetHttpContextAccessor(HttpContextBase httpContextBase = null) + { + var mock = new Mock(); + + var httpContext = UmbracoContextFactory.EnsureHttpContext(httpContextBase); + + mock.Setup(x => x.HttpContext).Returns(httpContext); + + return mock.Object; + } } } diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index faeb5b10ec..82cc0b196e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -31,6 +31,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.Testing.Objects.Accessors; +using Umbraco.Web.WebApi; namespace Umbraco.Tests.TestHelpers { @@ -81,6 +82,9 @@ namespace Umbraco.Tests.TestHelpers .Clear() .Add(() => Composition.TypeLoader.GetDataEditors()); + Composition.WithCollectionBuilder() + .Add(Composition.TypeLoader.GetUmbracoApiControllers()); + Composition.RegisterUnique(f => { if (Options.Database == UmbracoTestOptions.Database.None) diff --git a/src/Umbraco.Tests/Testing/Objects/Accessors/NoHttpContextAccessor.cs b/src/Umbraco.Tests/Testing/Objects/Accessors/NoHttpContextAccessor.cs index 9b37389241..e34ff7bb45 100644 --- a/src/Umbraco.Tests/Testing/Objects/Accessors/NoHttpContextAccessor.cs +++ b/src/Umbraco.Tests/Testing/Objects/Accessors/NoHttpContextAccessor.cs @@ -5,6 +5,6 @@ namespace Umbraco.Tests.Testing.Objects.Accessors { public class NoHttpContextAccessor : IHttpContextAccessor { - public HttpContext HttpContext { get; set; } = null; + public HttpContextBase HttpContext { get; set; } = null; } } diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 724eb29266..b712bcafc8 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Linq; +using System.Web; using System.Web.Security; using Moq; using NUnit.Framework; @@ -71,7 +72,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of())); + new MembershipHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of())); Assert.Pass(); } @@ -103,7 +104,7 @@ namespace Umbraco.Tests.Testing.TestingTests var memberService = Mock.Of(); var memberTypeService = Mock.Of(); var membershipProvider = new MembersMembershipProvider(memberService, memberTypeService, Mock.Of(), TestHelper.GetHostingEnvironment(), TestHelper.GetIpResolver()); - var membershipHelper = new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), membershipProvider, Mock.Of(), memberService, memberTypeService, Mock.Of(), AppCaches.Disabled, logger, ShortStringHelper, Mock.Of()); + var membershipHelper = new MembershipHelper(Mock.Of(), Mock.Of(), membershipProvider, Mock.Of(), memberService, memberTypeService, Mock.Of(), AppCaches.Disabled, logger, ShortStringHelper, Mock.Of()); var umbracoHelper = new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper); var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() })); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 93a3e52446..7999898c4e 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -138,6 +138,7 @@ namespace Umbraco.Tests.Testing protected IMapperCollection Mappers => Factory.GetInstance(); protected UmbracoMapper Mapper => Factory.GetInstance(); + protected IHttpContextAccessor HttpContextAccessor => Factory.GetInstance(); protected IRuntimeState RuntimeState => ComponentTests.MockRuntimeState(RuntimeLevel.Run); #endregion @@ -444,6 +445,9 @@ namespace Umbraco.Tests.Testing Composition.WithCollectionBuilder(); Composition.RegisterUnique(); Composition.RegisterUnique(); + + + Composition.RegisterUnique(TestObjects.GetHttpContextAccessor()); } #endregion diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index c54192f869..6a75fe5457 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -124,7 +124,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), Mock.Of(), Mock.Of(query => query.Content(2) == content.Object), - new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of())); + new MembershipHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), AppCaches.Disabled, Mock.Of(), ShortStringHelper, Mock.Of())); var ctrl = new TestSurfaceController(umbracoContextAccessor, helper); var result = ctrl.GetContent(2) as PublishedContentResult; @@ -159,7 +159,7 @@ namespace Umbraco.Tests.Web.Mvc var content = Mock.Of(publishedContent => publishedContent.Id == 12345); - var contextBase = umbracoContext.HttpContext; + var publishedRouter = BaseWebTest.CreatePublishedRouter(TestObjects.GetUmbracoSettings().WebRouting); var frequest = publishedRouter.CreateRequest(umbracoContext, new Uri("http://localhost/test")); frequest.PublishedContent = content; @@ -173,7 +173,7 @@ namespace Umbraco.Tests.Web.Mvc routeData.DataTokens.Add(Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); var ctrl = new TestSurfaceController(umbracoContextAccessor, new UmbracoHelper()); - ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl); + ctrl.ControllerContext = new ControllerContext(Mock.Of(), routeData, ctrl); var result = ctrl.GetContentFromCurrentPage() as PublishedContentResult; diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 5662883d2a..8a6862b018 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -28,12 +28,22 @@ namespace Umbraco.Web public class BatchedDatabaseServerMessenger : DatabaseServerMessenger { private readonly IUmbracoDatabaseFactory _databaseFactory; + private readonly IHttpContextAccessor _httpContextAccessor; public BatchedDatabaseServerMessenger( - IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers) + IRuntimeState runtime, + IUmbracoDatabaseFactory databaseFactory, + IScopeProvider scopeProvider, + ISqlContext sqlContext, + IProfilingLogger proflog, + DatabaseServerMessengerOptions options, + IHostingEnvironment hostingEnvironment, + CacheRefresherCollection cacheRefreshers, + IHttpContextAccessor httpContextAccessor) : base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers) { _databaseFactory = databaseFactory; + _httpContextAccessor = httpContextAccessor; } // invoked by DatabaseServerRegistrarAndMessengerComponent @@ -105,7 +115,7 @@ namespace Umbraco.Web // try get the http context from the UmbracoContext, we do this because in the case we are launching an async // thread and we know that the cache refreshers will execute, we will ensure the UmbracoContext and therefore we // can get the http context from it - var httpContext = (Current.UmbracoContext == null ? null : Current.UmbracoContext.HttpContext) + var httpContext = (_httpContextAccessor.HttpContext) // if this is null, it could be that an async thread is calling this method that we weren't aware of and the UmbracoContext // wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be // the case if the asp.net synchronization context has kicked in diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index d71f90aab5..38de699b7d 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text; using System.Web; using System.Web.Helpers; @@ -8,6 +9,9 @@ using System.Web.Mvc; using System.Web.Mvc.Html; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; using Umbraco.Web.Mvc; using Umbraco.Web.Security; using Current = Umbraco.Web.Composing.Current; @@ -56,14 +60,14 @@ namespace Umbraco.Web /// /// See: http://issues.umbraco.org/issue/U4-1614 /// - public static MvcHtmlString PreviewBadge(this HtmlHelper helper) + public static MvcHtmlString PreviewBadge(this HtmlHelper helper, IHttpContextAccessor httpContextAccessor, IGlobalSettings globalSettings, IIOHelper ioHelper, IUmbracoSettingsSection umbracoSettingsSection) { if (Current.UmbracoContext.InPreviewMode) { var htmlBadge = - String.Format(Current.Configs.Settings().Content.PreviewBadge, - Current.IOHelper.ResolveUrl(Current.Configs.Global().UmbracoPath), - Current.UmbracoContext.HttpContext.Server.UrlEncode(Current.UmbracoContext.HttpContext.Request.Path), + String.Format(umbracoSettingsSection.Content.PreviewBadge, + ioHelper.ResolveUrl(globalSettings.UmbracoPath), + WebUtility.UrlEncode(httpContextAccessor.HttpContext.Request.Path), Current.UmbracoContext.PublishedRequest.PublishedContent.Id); return new MvcHtmlString(htmlBadge); } diff --git a/src/Umbraco.Web/IHttpContextAccessor.cs b/src/Umbraco.Web/IHttpContextAccessor.cs index a00632803d..c83b9425a6 100644 --- a/src/Umbraco.Web/IHttpContextAccessor.cs +++ b/src/Umbraco.Web/IHttpContextAccessor.cs @@ -4,6 +4,6 @@ namespace Umbraco.Web { public interface IHttpContextAccessor { - HttpContext HttpContext { get; set; } + HttpContextBase HttpContext { get; set; } } } diff --git a/src/Umbraco.Web/IUmbracoContext.cs b/src/Umbraco.Web/IUmbracoContext.cs index 7609ad6b01..c0cee5e9ff 100644 --- a/src/Umbraco.Web/IUmbracoContext.cs +++ b/src/Umbraco.Web/IUmbracoContext.cs @@ -72,11 +72,6 @@ namespace Umbraco.Web /// PublishedRequest PublishedRequest { get; set; } - /// - /// Exposes the HttpContext for the current request - /// - HttpContextBase HttpContext { get; } - /// /// Gets the variation context accessor. /// diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index db13ff1ed7..fb809d1bfc 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Install { private static HttpClient _httpClient; private readonly DatabaseBuilder _databaseBuilder; - private readonly HttpContext _httpContext; + private readonly HttpContextBase _httpContext; private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; diff --git a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs index 7bf4a94b1c..ed047d2ad8 100644 --- a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs @@ -23,15 +23,17 @@ namespace Umbraco.Web.Models.Mapping private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ContentAppFactoryCollection _contentAppDefinitions; private readonly ILocalizedTextService _localizedTextService; + private readonly IHttpContextAccessor _httpContextAccessor; public CommonMapper(IUserService userService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, - ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService) + ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService, IHttpContextAccessor httpContextAccessor) { _userService = userService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; _umbracoContextAccessor = umbracoContextAccessor; _contentAppDefinitions = contentAppDefinitions; _localizedTextService = localizedTextService; + _httpContextAccessor = httpContextAccessor; } public UserProfile GetOwner(IContentBase source, MapperContext context) @@ -65,19 +67,19 @@ namespace Umbraco.Web.Models.Mapping public string GetTreeNodeUrl(IContentBase source) where TController : ContentTreeControllerBase { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; - if (umbracoContext == null) return null; + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) return null; - var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext); + var urlHelper = new UrlHelper(httpContext.Request.RequestContext); return urlHelper.GetUmbracoApiService(controller => controller.GetTreeNode(source.Key.ToString("N"), null)); } public string GetMemberTreeNodeUrl(IContentBase source) { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; - if (umbracoContext == null) return null; + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) return null; - var urlHelper = new UrlHelper(umbracoContext.HttpContext.Request.RequestContext); + var urlHelper = new UrlHelper(httpContext.Request.RequestContext); return urlHelper.GetUmbracoApiService(controller => controller.GetTreeNode(source.Key.ToString("N"), null)); } diff --git a/src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs b/src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs index babd8dfcfa..c7270a8259 100644 --- a/src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs +++ b/src/Umbraco.Web/Net/AspNetHttpContextAccessor.cs @@ -5,11 +5,11 @@ namespace Umbraco.Web { internal class AspNetHttpContextAccessor : IHttpContextAccessor { - public HttpContext HttpContext + public HttpContextBase HttpContext { get { - return HttpContext.Current; + return new HttpContextWrapper(System.Web.HttpContext.Current); } set { diff --git a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs index b339198928..5e0e3b2ace 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs @@ -16,12 +16,14 @@ namespace Umbraco.Web.Routing public class ContentFinderByIdPath : IContentFinder { private readonly ILogger _logger; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly IWebRoutingSection _webRoutingSection; - - public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger) + + public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger, IHttpContextAccessor httpContextAccessor) { _webRoutingSection = webRoutingSection ?? throw new System.ArgumentNullException(nameof(webRoutingSection)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + _httpContextAccessor = httpContextAccessor; } /// @@ -55,10 +57,10 @@ namespace Umbraco.Web.Routing if (node != null) { //if we have a node, check if we have a culture in the query string - if (frequest.UmbracoContext.HttpContext.Request.QueryString.ContainsKey("culture")) + if (_httpContextAccessor.HttpContext.Request.QueryString.ContainsKey("culture")) { //we're assuming it will match a culture, if an invalid one is passed in, an exception will throw (there is no TryGetCultureInfo method), i think this is ok though - frequest.Culture = CultureInfo.GetCultureInfo(frequest.UmbracoContext.HttpContext.Request.QueryString["culture"]); + frequest.Culture = CultureInfo.GetCultureInfo(_httpContextAccessor.HttpContext.Request.QueryString["culture"]); } frequest.PublishedContent = node; diff --git a/src/Umbraco.Web/Routing/ContentFinderByPageIdQuery.cs b/src/Umbraco.Web/Routing/ContentFinderByPageIdQuery.cs index 70a920f6f0..eb1abbb718 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByPageIdQuery.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByPageIdQuery.cs @@ -9,10 +9,17 @@ /// public class ContentFinderByPageIdQuery : IContentFinder { + private readonly IHttpContextAccessor _httpContextAccessor; + + public ContentFinderByPageIdQuery(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + public bool TryFindContent(PublishedRequest frequest) { int pageId; - if (int.TryParse(frequest.UmbracoContext.HttpContext.Request["umbPageID"], out pageId)) + if (int.TryParse(_httpContextAccessor.HttpContext.Request["umbPageID"], out pageId)) { var doc = frequest.UmbracoContext.Content.GetById(pageId); diff --git a/src/Umbraco.Web/Routing/PublishedRequest.cs b/src/Umbraco.Web/Routing/PublishedRequest.cs index becdbc8d27..13074fce07 100644 --- a/src/Umbraco.Web/Routing/PublishedRequest.cs +++ b/src/Umbraco.Web/Routing/PublishedRequest.cs @@ -12,11 +12,219 @@ using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Routing { + public interface IPublishedRequest + { + /// + /// Gets the UmbracoContext. + /// + IUmbracoContext UmbracoContext { get; } + + /// + /// Gets or sets the cleaned up Uri used for routing. + /// + /// The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc. + Uri Uri { get; set; } + + /// + /// Gets or sets a value indicating whether the Umbraco Backoffice should ignore a collision for this request. + /// + bool IgnorePublishedContentCollisions { get; set; } + + /// + /// Gets or sets the requested content. + /// + /// Setting the requested content clears Template. + IPublishedContent PublishedContent { get; set; } + + /// + /// Gets the initial requested content. + /// + /// The initial requested content is the content that was found by the finders, + /// before anything such as 404, redirect... took place. + IPublishedContent InitialPublishedContent { get; } + + /// + /// Gets value indicating whether the current published content is the initial one. + /// + bool IsInitialPublishedContent { get; } + + /// + /// Gets or sets a value indicating whether the current published content has been obtained + /// from the initial published content following internal redirections exclusively. + /// + /// Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to + /// apply the internal redirect or not, when content is not the initial content. + bool IsInternalRedirectPublishedContent { get; } + + /// + /// Gets a value indicating whether the content request has a content. + /// + bool HasPublishedContent { get; } + + /// + /// Gets the alias of the template to use to display the requested content. + /// + string TemplateAlias { get; } + + /// + /// Gets a value indicating whether the content request has a template. + /// + bool HasTemplate { get; } + + /// + /// Gets or sets the content request's domain. + /// + /// Is a DomainAndUri object ie a standard Domain plus the fully qualified uri. For example, + /// the Domain may contain "example.com" whereas the Uri will be fully qualified eg "http://example.com/". + DomainAndUri Domain { get; set; } + + /// + /// Gets a value indicating whether the content request has a domain. + /// + bool HasDomain { get; } + + /// + /// Gets or sets the content request's culture. + /// + CultureInfo Culture { get; set; } + + /// + /// Gets or sets a value indicating whether the requested content could not be found. + /// + /// This is set in the PublishedContentRequestBuilder and can also be used in + /// custom content finders or Prepared event handlers, where we want to allow developers + /// to indicate a request is 404 but not to cancel it. + bool Is404 { get; set; } + + /// + /// Gets a value indicating whether the content request triggers a redirect (permanent or not). + /// + bool IsRedirect { get; } + + /// + /// Gets or sets a value indicating whether the redirect is permanent. + /// + bool IsRedirectPermanent { get; } + + /// + /// Gets or sets the url to redirect to, when the content request triggers a redirect. + /// + string RedirectUrl { get; } + + /// + /// Gets or sets the content request http response status code. + /// + /// Does not actually set the http response status code, only registers that the response + /// should use the specified code. The code will or will not be used, in due time. + int ResponseStatusCode { get; } + + /// + /// Gets or sets the content request http response status description. + /// + /// Does not actually set the http response status description, only registers that the response + /// should use the specified description. The description will or will not be used, in due time. + string ResponseStatusDescription { get; } + + /// + /// Gets or sets the System.Web.HttpCacheability + /// +// Note: we used to set a default value here but that would then be the default +// for ALL requests, we shouldn't overwrite it though if people are using [OutputCache] for example +// see: https://our.umbraco.com/forum/using-umbraco-and-getting-started/79715-output-cache-in-umbraco-752 + HttpCacheability Cacheability { get; set; } + + /// + /// Gets or sets a list of Extensions to append to the Response.Cache object. + /// + List CacheExtensions { get; set; } + + /// + /// Gets or sets a dictionary of Headers to append to the Response object. + /// + Dictionary Headers { get; set; } + + /// + /// Prepares the request. + /// + void Prepare(); + + /// + /// Sets the requested content, following an internal redirect. + /// + /// The requested content. + /// Depending on UmbracoSettings.InternalRedirectPreservesTemplate, will + /// preserve or reset the template, if any. + void SetInternalRedirectPublishedContent(IPublishedContent content); + + /// + /// Indicates that the current PublishedContent is the initial one. + /// + void SetIsInitialPublishedContent(); + + /// + /// Tries to set the template to use to display the requested content. + /// + /// The alias of the template. + /// A value indicating whether a valid template with the specified alias was found. + /// + /// Successfully setting the template does refresh RenderingEngine. + /// If setting the template fails, then the previous template (if any) remains in place. + /// + bool TrySetTemplate(string alias); + + /// + /// Sets the template to use to display the requested content. + /// + /// The template. + /// Setting the template does refresh RenderingEngine. + void SetTemplate(ITemplate template); + + /// + /// Resets the template. + /// + void ResetTemplate(); + + /// + /// Indicates that the content request should trigger a redirect (302). + /// + /// The url to redirect to. + /// Does not actually perform a redirect, only registers that the response should + /// redirect. Redirect will or will not take place in due time. + void SetRedirect(string url); + + /// + /// Indicates that the content request should trigger a permanent redirect (301). + /// + /// The url to redirect to. + /// Does not actually perform a redirect, only registers that the response should + /// redirect. Redirect will or will not take place in due time. + void SetRedirectPermanent(string url); + + /// + /// Indicates that the content request should trigger a redirect, with a specified status code. + /// + /// The url to redirect to. + /// The status code (300-308). + /// Does not actually perform a redirect, only registers that the response should + /// redirect. Redirect will or will not take place in due time. + void SetRedirect(string url, int status); + + /// + /// Sets the http response status code, along with an optional associated description. + /// + /// The http status code. + /// The description. + /// Does not actually set the http response status code and description, only registers that + /// the response should use the specified code and description. The code and description will or will + /// not be used, in due time. + void SetResponseStatus(int code, string description = null); + } + /// /// Represents a request for one specified Umbraco IPublishedContent to be rendered /// by one specified template, using one specified Culture and RenderingEngine. /// - public class PublishedRequest + public class PublishedRequest : IPublishedRequest { private readonly IPublishedRouter _publishedRouter; private readonly IUmbracoSettingsSection _umbracoSettingsSection; diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 82041f04fa..1afbaceccf 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -29,6 +29,7 @@ namespace Umbraco.Web.Routing private readonly ILogger _logger; private readonly IUmbracoSettingsSection _umbracoSettingsSection; private readonly IUserService _userService; + private readonly IHttpContextAccessor _httpContextAccessor; /// /// Initializes a new instance of the class. @@ -41,7 +42,8 @@ namespace Umbraco.Web.Routing ServiceContext services, IProfilingLogger proflog, IUmbracoSettingsSection umbracoSettingsSection, - IUserService userService) + IUserService userService, + IHttpContextAccessor httpContextAccessor) { _webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection)); _contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders)); @@ -52,6 +54,7 @@ namespace Umbraco.Web.Routing _logger = proflog; _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _httpContextAccessor = httpContextAccessor; } /// @@ -651,7 +654,7 @@ namespace Umbraco.Web.Routing var useAltTemplate = request.IsInitialPublishedContent || (_webRoutingSection.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent); var altTemplate = useAltTemplate - ? request.UmbracoContext.HttpContext.Request[Constants.Conventions.Url.AltTemplate] + ? _httpContextAccessor.HttpContext.Request[Constants.Conventions.Url.AltTemplate] : null; if (string.IsNullOrWhiteSpace(altTemplate)) diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 48d1a58b2d..e283b4d6a0 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -98,7 +98,7 @@ namespace Umbraco.Web.Runtime // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); + composition.Register(factory => factory.GetInstance().HttpContext, Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.RegisterUnique(); diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 4b0093f910..ba7a42630a 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -127,7 +127,7 @@ namespace Umbraco.Web.Templates //var queryString = _umbracoContext.HttpContext.Request.QueryString.AllKeys // .ToDictionary(key => key, key => context.Request.QueryString[key]); - var requestContext = new RequestContext(new HttpContextWrapper(_httpContextAccessor.HttpContext), new RouteData() + var requestContext = new RequestContext(_httpContextAccessor.HttpContext, new RouteData() { Route = RouteTable.Routes["Umbraco_default"] }); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a02b3d6c55..408951eba6 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -789,7 +789,7 @@ - +