diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index 772b249132..a6507632f8 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -154,6 +154,9 @@ namespace Umbraco.Core /// internal virtual void ConfigureCoreServices(ServiceContainer container) { + // configure the temp. Current + Current.Container = container; + container.Register(factory => container); //Logging diff --git a/src/Umbraco.Core/Current.cs b/src/Umbraco.Core/Current.cs new file mode 100644 index 0000000000..334ba2e988 --- /dev/null +++ b/src/Umbraco.Core/Current.cs @@ -0,0 +1,11 @@ +using LightInject; + +namespace Umbraco.Core +{ + // kill this eventually - it's here during the transition + // provides static access to singletons + internal class Current + { + public static IServiceContainer Container { get; set; } // ok to set - don't be stupid + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index fcb2c701bb..d2d239d580 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -205,6 +205,7 @@ + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 974c5c718b..7cc46aa59a 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -1,6 +1,4 @@ using System; -using System.Diagnostics; -using System.Linq; using System.Reflection; using System.Threading; using System.Web; @@ -8,8 +6,6 @@ using System.Web.Hosting; using log4net; using LightInject; using Umbraco.Core.Logging; -using Umbraco.Core.ObjectResolution; -using Umbraco.Core.Logging; namespace Umbraco.Core { @@ -18,16 +14,16 @@ namespace Umbraco.Core /// The abstract class for the Umbraco HttpApplication /// /// - /// This is exposed in the core so that we can have the IApplicationEventHandler in the core project so that + /// This is exposed in the core so that we can have the IApplicationEventHandler in the core project so that /// IApplicationEventHandler's can fire/execute outside of the web contenxt (i.e. in console applications) /// - public abstract class UmbracoApplicationBase : System.Web.HttpApplication + public abstract class UmbracoApplicationBase : HttpApplication { /// /// Umbraco application's IoC container /// - internal ServiceContainer Container { get; private set; } + internal ServiceContainer Container { get; } private ILogger _logger; @@ -53,14 +49,14 @@ namespace Umbraco.Core public static event EventHandler ApplicationInit; public static event EventHandler ApplicationError; public static event EventHandler ApplicationEnd; - + /// /// Boots up the Umbraco application /// internal void StartApplication(object sender, EventArgs e) { - //take care of unhandled exceptions - there is nothing we can do to + //take care of unhandled exceptions - there is nothing we can do to // prevent the entire w3wp process to go down but at least we can try // and log the exception AppDomain.CurrentDomain.UnhandledException += (_, args) => @@ -123,7 +119,7 @@ namespace Umbraco.Core throw; } } - + } /// @@ -191,7 +187,7 @@ namespace Umbraco.Core { return; } - + Logger.Error("An unhandled exception occurred", exc); OnApplicationError(sender, e); diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index 5548bfc2ab..f6265e7432 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Security new WebSecurity(Mock.Of(), appCtx), Mock.Of(), new List(), false); - var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.Value == umbCtx)); + var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx)); var result = mgr.ShouldAuthenticateRequest(Mock.Of(), new Uri("http://localhost/umbraco")); @@ -70,7 +70,7 @@ namespace Umbraco.Tests.Security new WebSecurity(Mock.Of(), appCtx), Mock.Of(), new List(), false); - var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.Value == umbCtx)); + var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx)); var request = new Mock(); request.Setup(owinRequest => owinRequest.Uri).Returns(new Uri("http://localhost/umbraco")); diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index 821d41b984..1accdb705a 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -58,7 +58,7 @@ namespace Umbraco.Tests.Services [TearDown] public override void TearDown() - { + { base.TearDown(); } @@ -87,7 +87,7 @@ namespace Umbraco.Tests.Services } Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); } - + } using (DisposableTimer.DebugDuration("Getting published content optimized")) @@ -119,7 +119,7 @@ namespace Umbraco.Tests.Services //do this 10x! for (var i = 0; i < 10; i++) { - + //get all content items that are published of this type var published = contentSvc.GetContentOfContentType(contentTypeId).Where(content => content.Published); Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); @@ -146,7 +146,7 @@ namespace Umbraco.Tests.Services //chuck lots of data in the db var nodes = PrimeDbWithLotsOfContentXmlRecords(customObjectType); - //now we need to test the difference between truncating all records and re-inserting them as we do now, + //now we need to test the difference between truncating all records and re-inserting them as we do now, //vs updating them (which might result in checking if they exist for or listening on an exception). using (DisposableTimer.DebugDuration("Starting truncate + normal insert test")) { @@ -155,7 +155,7 @@ namespace Umbraco.Tests.Services { //clear all the xml entries DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN - (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml + (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)"); //now we insert each record for the ones we've deleted like we do in the content service. @@ -169,7 +169,7 @@ namespace Umbraco.Tests.Services //now, isntead of truncating, we'll attempt to update and if it doesn't work then we insert using (DisposableTimer.DebugDuration("Starting update test")) - { + { //do this 10x! for (var i = 0; i < 10; i++) { @@ -190,7 +190,7 @@ namespace Umbraco.Tests.Services { //clear all the xml entries DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN - (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml + (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)"); //now we insert each record for the ones we've deleted like we do in the content service. @@ -212,31 +212,31 @@ namespace Umbraco.Tests.Services { //clear all the xml entries DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN - (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml + (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)"); - DatabaseContext.Database.BulkInsertRecords(SqlSyntax, xmlItems, tr); + DatabaseContext.Database.BulkInsertRecords(SqlSyntax, xmlItems); tr.Complete(); } } } - + } private IEnumerable PrimeDbWithLotsOfContent() { var contentType1 = MockedContentTypes.CreateSimpleContentType(); - contentType1.AllowedAsRoot = true; + contentType1.AllowedAsRoot = true; ServiceContext.ContentTypeService.Save(contentType1); contentType1.AllowedContentTypes = new List { new ContentTypeSort(new Lazy(() => contentType1.Id), 0, contentType1.Alias) }; var result = new List(); - ServiceContext.ContentTypeService.Save(contentType1); + ServiceContext.ContentTypeService.Save(contentType1); IContent lastParent = MockedContent.CreateSimpleContent(contentType1); ServiceContext.ContentService.SaveAndPublish(lastParent); result.Add(lastParent); @@ -251,7 +251,7 @@ namespace Umbraco.Tests.Services //only publish evens if (j % 2 == 0) { - ServiceContext.ContentService.SaveAndPublish(content); + ServiceContext.ContentService.SaveAndPublish(content); } else { @@ -259,12 +259,12 @@ namespace Umbraco.Tests.Services } result.Add(content); } - + //assign the last one as the next parent lastParent = content; } return result; - } + } private IEnumerable PrimeDbWithLotsOfContentXmlRecords(Guid customObjectType) { diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index 6dcc29d709..3f540c7d0e 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -293,10 +293,11 @@ namespace Umbraco.Tests.TestHelpers ApplicationContext.Services.MemberTypeService); // testing=true so XmlStore will not use the file nor the database + var facadeAccessor = new TestFacadeAccessor(); var service = new FacadeService( ApplicationContext.Services, _uowProvider, - cache, ContentTypesCache, true, enableRepositoryEvents); + cache, facadeAccessor, ContentTypesCache, true, enableRepositoryEvents); // initialize PublishedCacheService content with an Xml source service.XmlStore.GetXmlDocument = () => diff --git a/src/Umbraco.Tests/TestHelpers/TestFacadeAccessor.cs b/src/Umbraco.Tests/TestHelpers/TestFacadeAccessor.cs new file mode 100644 index 0000000000..34ab185e71 --- /dev/null +++ b/src/Umbraco.Tests/TestHelpers/TestFacadeAccessor.cs @@ -0,0 +1,9 @@ +using Umbraco.Web.PublishedCache; + +namespace Umbraco.Tests.TestHelpers +{ + class TestFacadeAccessor : IFacadeAccessor + { + public IFacade Facade { get; set; } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index f48713ba26..043e1479ca 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -235,6 +235,7 @@ + diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 64fcdb8ebb..7b30182b59 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -300,7 +300,7 @@ namespace Umbraco.Tests.Web.Mvc view.ViewContext = GetViewContext(); Assert.Throws(() =>view.SetViewDataX(viewData)); } - + [Test] public void ContentType1_To_ContentType1() { @@ -337,7 +337,7 @@ namespace Umbraco.Tests.Web.Mvc Assert.IsInstanceOf(view.Model); } - + #endregion #region Test elements @@ -409,7 +409,7 @@ namespace Umbraco.Tests.Web.Mvc umbracoContext.RoutingContext = routingContext; var request = new PublishedContentRequest( - new Uri("http://localhost/dang"), + new Uri("http://localhost/dang"), routingContext, settings.WebRouting, s => Enumerable.Empty()); @@ -438,10 +438,10 @@ namespace Umbraco.Tests.Web.Mvc var cache = new NullCacheProvider(); var provider = new NPocoUnitOfWorkProvider(databaseFactory, new RepositoryFactory(Mock.Of())); - _service = new FacadeService(svcCtx, provider, cache, Enumerable.Empty(), true, false); // no events + _service = new FacadeService(svcCtx, provider, cache, Enumerable.Empty(), null, true, false); // no events var http = GetHttpContextFactory(url, routeData).HttpContext; - + var ctx = UmbracoContext.CreateContext( GetHttpContextFactory(url, routeData).HttpContext, appCtx, _service, @@ -462,7 +462,7 @@ namespace Umbraco.Tests.Web.Mvc var factory = routeData != null ? new FakeHttpContextFactory(url, routeData) : new FakeHttpContextFactory(url); - + return factory; } diff --git a/src/Umbraco.Web.UI/umbraco/endPreview.aspx b/src/Umbraco.Web.UI/umbraco/endPreview.aspx index 05fc2ddd25..3ab2a94006 100644 --- a/src/Umbraco.Web.UI/umbraco/endPreview.aspx +++ b/src/Umbraco.Web.UI/umbraco/endPreview.aspx @@ -1,25 +1,3 @@ -<%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %> +<%@ Page Language="C#" AutoEventWireup="true" Inherits="umbraco.presentation.endPreview" %> - \ No newline at end of file + diff --git a/src/Umbraco.Web/Current.cs b/src/Umbraco.Web/Current.cs new file mode 100644 index 0000000000..0a31387911 --- /dev/null +++ b/src/Umbraco.Web/Current.cs @@ -0,0 +1,17 @@ +using LightInject; +using Umbraco.Core; +using Umbraco.Web.PublishedCache; + +namespace Umbraco.Web +{ + // kill this eventually - it's here during the transition + // provides static access to singletons + internal static class Current + { + public static IServiceContainer Container { get; set; } // ok to set - don't be stupid + + public static UmbracoContext UmbracoContext => Container.GetInstance().UmbracoContext; + + public static IFacade Facade => Container.GetInstance().Facade; + } +} diff --git a/src/Umbraco.Web/DefaultUmbracoContextAccessor.cs b/src/Umbraco.Web/DefaultUmbracoContextAccessor.cs index 3bd7d5f95b..5b15c338f4 100644 --- a/src/Umbraco.Web/DefaultUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/DefaultUmbracoContextAccessor.cs @@ -11,9 +11,6 @@ namespace Umbraco.Web _umbracoContext = umbracoContext; } - public UmbracoContext Value - { - get { return _umbracoContext(); } - } + public UmbracoContext UmbracoContext => _umbracoContext(); } } \ No newline at end of file diff --git a/src/Umbraco.Web/IUmbracoContextAccessor.cs b/src/Umbraco.Web/IUmbracoContextAccessor.cs index 8111606602..3f0f9580a6 100644 --- a/src/Umbraco.Web/IUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/IUmbracoContextAccessor.cs @@ -1,13 +1,10 @@ namespace Umbraco.Web { /// - /// Used to retrieve the Umbraco context + /// Provides access to UmbracoContext. /// - /// - /// NOTE: This has a singleton lifespan - /// public interface IUmbracoContextAccessor { - UmbracoContext Value { get; } + UmbracoContext UmbracoContext { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Install/FilePermissionHelper.cs b/src/Umbraco.Web/Install/FilePermissionHelper.cs index 416a9d02e2..bdb8243d06 100644 --- a/src/Umbraco.Web/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Web/Install/FilePermissionHelper.cs @@ -99,6 +99,7 @@ namespace Umbraco.Web.Install errorReport = new List(); // makes sense for xml cache only + // fixme and to nucache that writes files too? var svc = FacadeServiceResolver.Current.Service as FacadeService; if (svc == null) return true; diff --git a/src/Umbraco.Web/PublishedCache/FacadeServiceBase.cs b/src/Umbraco.Web/PublishedCache/FacadeServiceBase.cs index accc3e0f05..b61eac3889 100644 --- a/src/Umbraco.Web/PublishedCache/FacadeServiceBase.cs +++ b/src/Umbraco.Web/PublishedCache/FacadeServiceBase.cs @@ -1,5 +1,4 @@ using System; -using Umbraco.Core.ObjectResolution; using Umbraco.Core.Models.Membership; using Umbraco.Web.Cache; @@ -7,30 +6,18 @@ namespace Umbraco.Web.PublishedCache { abstract class FacadeServiceBase : IFacadeService { - // FIXME need a facade accessor of some sort? to init the facade service! of course! - private Func _getFacadeFunc = () => UmbracoContext.Current == null ? null : UmbracoContext.Current.Facade; + private IFacadeAccessor _facadeAccessor; - public Func GetFacadeFunc + protected FacadeServiceBase(IFacadeAccessor facadeAccessor) { - get { return _getFacadeFunc; } - set - { - using (Resolution.Configuration) - { - _getFacadeFunc = value; - } - } + _facadeAccessor = facadeAccessor; } + // note: NOT setting _facadeAccessor.Facade here because it is the + // responsibility of the caller to manage what the 'current' facade is public abstract IFacade CreateFacade(string previewToken); - public IFacade GetFacade() - { - var caches = _getFacadeFunc(); - if (caches == null) - throw new Exception("Carrier's caches is null."); - return caches; - } + protected IFacade CurrentFacade => _facadeAccessor.Facade; public abstract string EnterPreview(IUser user, int contentId); public abstract void RefreshPreview(string previewToken, int contentId); diff --git a/src/Umbraco.Web/PublishedCache/IFacadeAccessor.cs b/src/Umbraco.Web/PublishedCache/IFacadeAccessor.cs new file mode 100644 index 0000000000..208e476edf --- /dev/null +++ b/src/Umbraco.Web/PublishedCache/IFacadeAccessor.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Web.PublishedCache +{ + /// + /// Provides access to IFacade. + /// + interface IFacadeAccessor + { + IFacade Facade { get; set; } + } +} diff --git a/src/Umbraco.Web/PublishedCache/IFacadeService.cs b/src/Umbraco.Web/PublishedCache/IFacadeService.cs index 5cdcbc6182..22d95a06a2 100644 --- a/src/Umbraco.Web/PublishedCache/IFacadeService.cs +++ b/src/Umbraco.Web/PublishedCache/IFacadeService.cs @@ -37,13 +37,6 @@ namespace Umbraco.Web.PublishedCache /// A facade. IFacade CreateFacade(string previewToken); - /// - /// Gets the current facade. - /// - /// The current facade. - /// - IFacade GetFacade(); - #endregion #region Preview diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs index 040d1017a9..366131d763 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs @@ -177,7 +177,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // we add this check - we look for the document matching "/" and if it's not us, then // we do not hide the top level path // it has to be taken care of in GetByRoute too so if - // "/foo" fails (looking for "/*/foo") we try also "/foo". + // "/foo" fails (looking for "/*/foo") we try also "/foo". // this does not make much sense anyway esp. if both "/foo/" and "/bar/foo" exist, but // that's the way it works pre-4.10 and we try to be backward compat for the time being if (content.Parent == null) @@ -222,12 +222,9 @@ namespace Umbraco.Web.PublishedCache.NuCache if (FacadeService.CacheContentCacheRoots == false) return GetAtRootNoCache(preview); - var facade = Facade.Current; - var cache = (facade == null) - ? null - : (preview == false || FacadeService.FullCacheWhenPreviewing - ? facade.SnapshotCache - : facade.FacadeCache); + var cache = preview == false || FacadeService.FullCacheWhenPreviewing + ? _snapshotCache + : _facadeCache; if (cache == null) return GetAtRootNoCache(preview); @@ -253,7 +250,7 @@ namespace Umbraco.Web.PublishedCache.NuCache internal static IPublishedContent GetPublishedContentAsPreviewing(IPublishedContent content /*, bool preview*/) { if (content == null /*|| preview == false*/) return null; //content; - + // an object in the cache is either an IPublishedContentOrMedia, // or a model inheriting from PublishedContentExtended - in which // case we need to unwrap to get to the original IPublishedContentOrMedia. diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentNode.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentNode.cs index 709662c249..8c490bc1d3 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentNode.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentNode.cs @@ -33,10 +33,11 @@ namespace Umbraco.Web.PublishedCache.NuCache int level, string path, int sortOrder, int parentContentId, DateTime createDate, int creatorId, - ContentData draftData, ContentData publishedData) + ContentData draftData, ContentData publishedData, + IFacadeAccessor facadeAccessor) : this(id, uid, level, path, sortOrder, parentContentId, createDate, creatorId) { - SetContentTypeAndData(contentType, draftData, publishedData); + SetContentTypeAndData(contentType, draftData, publishedData, facadeAccessor); } // 2-phases ctor, phase 1 @@ -58,7 +59,7 @@ namespace Umbraco.Web.PublishedCache.NuCache } // two-phase ctor, phase 2 - public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData) + public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData, IFacadeAccessor facadeAccessor) { ContentType = contentType; @@ -66,13 +67,13 @@ namespace Umbraco.Web.PublishedCache.NuCache throw new ArgumentException("Both draftData and publishedData cannot be null at the same time."); if (draftData != null) - Draft = new PublishedContent(this, draftData).CreateModel(); + Draft = new PublishedContent(this, draftData, facadeAccessor).CreateModel(); if (publishedData != null) - Published = new PublishedContent(this, publishedData).CreateModel(); + Published = new PublishedContent(this, publishedData, facadeAccessor).CreateModel(); } // clone parent - private ContentNode(ContentNode origin) + private ContentNode(ContentNode origin, IFacadeAccessor facadeAccessor) { // everything is the same, except for the child items // list which is a clone of the original list @@ -90,14 +91,14 @@ namespace Umbraco.Web.PublishedCache.NuCache var originDraft = origin.Draft == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Draft); var originPublished = origin.Published == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Published); - Draft = originDraft == null ? null : new PublishedContent(this, originDraft).CreateModel(); - Published = originPublished == null ? null : new PublishedContent(this, originPublished).CreateModel(); + Draft = originDraft == null ? null : new PublishedContent(this, originDraft, facadeAccessor).CreateModel(); + Published = originPublished == null ? null : new PublishedContent(this, originPublished, facadeAccessor).CreateModel(); ChildContentIds = new List(origin.ChildContentIds); // needs to be *another* list } // clone with new content type - public ContentNode(ContentNode origin, PublishedContentType contentType) + public ContentNode(ContentNode origin, PublishedContentType contentType, IFacadeAccessor facadeAccessor) { Id = origin.Id; Uid = origin.Uid; @@ -112,8 +113,8 @@ namespace Umbraco.Web.PublishedCache.NuCache var originDraft = origin.Draft == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Draft); var originPublished = origin.Published == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Published); - Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData).CreateModel(); - Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData).CreateModel(); + Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData, facadeAccessor).CreateModel(); + Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData, facadeAccessor).CreateModel(); ChildContentIds = origin.ChildContentIds; // can be the *same* list FIXME oh really? } @@ -135,9 +136,9 @@ namespace Umbraco.Web.PublishedCache.NuCache public IPublishedContent Draft; public IPublishedContent Published; - public ContentNode CloneParent() + public ContentNode CloneParent(IFacadeAccessor facadeAccessor) { - return new ContentNode(this); + return new ContentNode(this, facadeAccessor); } public ContentNodeKit ToKit() diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentNodeKit.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentNodeKit.cs index c45b774486..7493f67e57 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentNodeKit.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentNodeKit.cs @@ -11,11 +11,11 @@ namespace Umbraco.Web.PublishedCache.NuCache public ContentData DraftData; public ContentData PublishedData; - public bool IsEmpty { get { return Node == null; } } + public bool IsEmpty => Node == null; - public void Build(PublishedContentType contentType) + public void Build(PublishedContentType contentType, IFacadeAccessor facadeAccessor) { - Node.SetContentTypeAndData(contentType, DraftData, PublishedData); + Node.SetContentTypeAndData(contentType, DraftData, PublishedData, facadeAccessor); } } } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore2.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore2.cs index e4826a38d9..825bcd0fce 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentStore2.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentStore2.cs @@ -17,6 +17,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // most of the snapshots management code, etc is an exact copy // SnapDictionary has unit tests to ensure it all works correctly + private readonly IFacadeAccessor _facadeAccessor; private readonly ConcurrentDictionary> _contentNodes; private readonly ConcurrentDictionary> _contentRootNodes; private readonly ConcurrentDictionary> _contentTypesById; @@ -40,8 +41,9 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Ctor - public ContentStore2(ILogger logger, BPlusTree localDb = null) + public ContentStore2(IFacadeAccessor facadeAccessor, ILogger logger, BPlusTree localDb = null) { + _facadeAccessor = facadeAccessor; _logger = logger; _localDb = localDb; @@ -270,7 +272,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentNodes.TryGetValue(id, out link); if (link == null || link.Value == null) continue; - var node = new ContentNode(link.Value, contentType); + var node = new ContentNode(link.Value, contentType, _facadeAccessor); SetValueLocked(_contentNodes, id, node); if (_localDb != null) _localDb[id] = node.ToKit(); @@ -302,7 +304,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentTypeNodes[kit.ContentTypeId].Add(kit.Node.Id); // and use - kit.Build(link.Value); + kit.Build(link.Value, _facadeAccessor); return true; } @@ -511,7 +513,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var link = GetParentLink(content); var parent = link.Value; if (link.Gen < _liveGen) - parent = parent.CloneParent(); + parent = parent.CloneParent(_facadeAccessor); parent.ChildContentIds.Remove(content.Id); if (link.Gen < _liveGen) SetValueLocked(_contentNodes, parent.Id, parent); @@ -541,7 +543,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var link = GetParentLink(content); var parent = link.Value; if (link.Gen < _liveGen) - parent = parent.CloneParent(); + parent = parent.CloneParent(_facadeAccessor); parent.ChildContentIds.Add(content.Id); if (link.Gen < _liveGen) SetValueLocked(_contentNodes, parent.Id, parent); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/Facade.cs b/src/Umbraco.Web/PublishedCache/NuCache/Facade.cs index fc9c36eab9..2d72307656 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/Facade.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/Facade.cs @@ -1,7 +1,5 @@ using System; -using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.ObjectResolution; namespace Umbraco.Web.PublishedCache.NuCache { @@ -37,75 +35,34 @@ namespace Umbraco.Web.PublishedCache.NuCache } } - private FacadeElements Elements - { - get - { - // no lock - facades are single-thread - return _elements ?? (_elements = _service.GetElements(_defaultPreview)); - } - } + private FacadeElements Elements => _elements ?? (_elements = _service.GetElements(_defaultPreview)); public void Resync() { // no lock - facades are single-thread - if (_elements != null) - _elements.Dispose(); + _elements?.Dispose(); _elements = null; } #endregion - #region Current - for tests - - private static Func _getCurrentFacadeFunc = () => - { -#if DEBUG - if (FacadeServiceResolver.HasCurrent == false) return null; - var service = FacadeServiceResolver.Current.Service as FacadeService; - if (service == null) return null; - return (Facade) service.GetFacadeFunc(); -#else - return (Facade) ((FacadeService) FacadeServiceResolver.Current.Service).GetFacadeFunc(); -#endif - }; - - public static Func GetCurrentFacadeFunc - { - get { return _getCurrentFacadeFunc; } - set - { - using (Resolution.Configuration) - { - _getCurrentFacadeFunc = value; - } - } - } - - public static Facade Current - { - get { return _getCurrentFacadeFunc(); } - } - - #endregion - #region Caches public ICacheProvider FacadeCache { get; private set; } - public ICacheProvider SnapshotCache { get { return Elements.SnapshotCache; } } + public ICacheProvider SnapshotCache => Elements.SnapshotCache; #endregion #region IFacade - public IPublishedContentCache ContentCache { get { return Elements.ContentCache; } } + public IPublishedContentCache ContentCache => Elements.ContentCache; - public IPublishedMediaCache MediaCache { get { return Elements.MediaCache; } } + public IPublishedMediaCache MediaCache => Elements.MediaCache; - public IPublishedMemberCache MemberCache { get { return Elements.MemberCache; } } + public IPublishedMemberCache MemberCache => Elements.MemberCache; - public IDomainCache DomainCache { get { return Elements.DomainCache; } } + public IDomainCache DomainCache => Elements.DomainCache; #endregion @@ -117,8 +74,7 @@ namespace Umbraco.Web.PublishedCache.NuCache { if (_disposed) return; _disposed = true; - if (_elements != null) - _elements.Dispose(); + _elements?.Dispose(); } #endregion diff --git a/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs b/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs index eae83ad54f..c0d6d2f2f5 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs @@ -32,6 +32,7 @@ namespace Umbraco.Web.PublishedCache.NuCache { class FacadeService : FacadeServiceBase { + private readonly IFacadeAccessor _facadeAccessor; private readonly ServiceContext _serviceContext; private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly Database _dataSource; @@ -70,8 +71,10 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Constructors - public FacadeService(Options options, MainDom mainDom, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, ILogger logger) + public FacadeService(Options options, MainDom mainDom, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, IFacadeAccessor facadeAccessor, ILogger logger) + : base(facadeAccessor) { + _facadeAccessor = facadeAccessor; _serviceContext = serviceContext; _uowProvider = uowProvider; _dataSource = new Database(); @@ -120,13 +123,13 @@ namespace Umbraco.Web.PublishedCache.NuCache // stores are created with a db so they can write to it, but they do not read from it, // stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to // figure out whether it can read the dbs or it should populate them from sql - _contentStore = new ContentStore2(logger, _localContentDb); - _mediaStore = new ContentStore2(logger, _localMediaDb); + _contentStore = new ContentStore2(facadeAccessor, logger, _localContentDb); + _mediaStore = new ContentStore2(facadeAccessor, logger, _localMediaDb); } else { - _contentStore = new ContentStore2(logger); - _mediaStore = new ContentStore2(logger); + _contentStore = new ContentStore2(facadeAccessor, logger); + _mediaStore = new ContentStore2(facadeAccessor, logger); } _domainStore = new SnapDictionary(); @@ -477,7 +480,7 @@ namespace Umbraco.Web.PublishedCache.NuCache publishedChanged = publishedChanged2; if (draftChanged || publishedChanged) - Facade.Current.Resync(); + ((Facade)CurrentFacade).Resync(); } private void NotifyLocked(IEnumerable payloads, out bool draftChanged, out bool publishedChanged) @@ -575,7 +578,7 @@ namespace Umbraco.Web.PublishedCache.NuCache anythingChanged = anythingChanged2; if (anythingChanged) - Facade.Current.Resync(); + ((Facade)CurrentFacade).Resync(); } private void NotifyLocked(IEnumerable payloads, out bool anythingChanged) @@ -697,7 +700,7 @@ namespace Umbraco.Web.PublishedCache.NuCache RefreshMediaTypesLocked(removedIds, refreshedIds); }); - Facade.Current.Resync(); + ((Facade)CurrentFacade).Resync(); } public override void Notify(DataTypeCacheRefresher.JsonPayload[] payloads) @@ -735,7 +738,7 @@ namespace Umbraco.Web.PublishedCache.NuCache } })); - Facade.Current.Resync(); + ((Facade) CurrentFacade).Resync(); } public override void Notify(DomainCacheRefresher.JsonPayload[] payloads) @@ -926,8 +929,8 @@ namespace Umbraco.Web.PublishedCache.NuCache return new Facade.FacadeElements { ContentCache = new ContentCache(previewDefault, contentSnap, facadeCache, snapshotCache, new DomainHelper(domainCache)), - MediaCache = new MediaCache(previewDefault, mediaSnap), - MemberCache = new MemberCache(previewDefault, _serviceContext.MemberService, _serviceContext.DataTypeService, memberTypeCache), + MediaCache = new MediaCache(previewDefault, mediaSnap, facadeCache, snapshotCache), + MemberCache = new MemberCache(previewDefault, facadeCache, _serviceContext.MemberService, _serviceContext.DataTypeService, memberTypeCache, _facadeAccessor), DomainCache = domainCache, FacadeCache = facadeCache, SnapshotCache = snapshotCache diff --git a/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs index 2c4da662b1..0f122a5782 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.XPath; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Xml; @@ -14,13 +15,17 @@ namespace Umbraco.Web.PublishedCache.NuCache class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable { private readonly ContentStore2.Snapshot _snapshot; + private readonly ICacheProvider _facadeCache; + private readonly ICacheProvider _snapshotCache; #region Constructors - public MediaCache(bool previewDefault, ContentStore2.Snapshot snapshot) + public MediaCache(bool previewDefault, ContentStore2.Snapshot snapshot, ICacheProvider facadeCache, ICacheProvider snapshotCache) : base(previewDefault) { _snapshot = snapshot; + _facadeCache = facadeCache; + _snapshotCache = snapshotCache; } #endregion @@ -30,7 +35,7 @@ namespace Umbraco.Web.PublishedCache.NuCache public override IPublishedContent GetById(bool preview, int contentId) { var n = _snapshot.Get(contentId); - return n == null ? null : n.Published; + return n?.Published; } public override bool HasById(bool preview, int contentId) @@ -44,12 +49,9 @@ namespace Umbraco.Web.PublishedCache.NuCache if (FacadeService.CacheContentCacheRoots == false) return GetAtRootNoCache(preview); - var facade = Facade.Current; - var cache = (facade == null) - ? null - : (preview == false || FacadeService.FullCacheWhenPreviewing - ? facade.SnapshotCache - : facade.FacadeCache); + var cache = preview == false || FacadeService.FullCacheWhenPreviewing + ? _snapshotCache + : _facadeCache; if (cache == null) return GetAtRootNoCache(preview); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs index c6a8f3b0fa..16115f7624 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs @@ -15,13 +15,17 @@ namespace Umbraco.Web.PublishedCache.NuCache { class MemberCache : IPublishedMemberCache, INavigableData { + private readonly IFacadeAccessor _facadeAccessor; + private readonly ICacheProvider _facadeCache; private readonly IMemberService _memberService; private readonly IDataTypeService _dataTypeService; private readonly PublishedContentTypeCache _contentTypeCache; private readonly bool _previewDefault; - public MemberCache(bool previewDefault, IMemberService memberService, IDataTypeService dataTypeService, PublishedContentTypeCache contentTypeCache) + public MemberCache(bool previewDefault, ICacheProvider facadeCache, IMemberService memberService, IDataTypeService dataTypeService, PublishedContentTypeCache contentTypeCache, IFacadeAccessor facadeAccessor) { + _facadeCache = facadeCache; + _facadeAccessor = facadeAccessor; _memberService = memberService; _dataTypeService = dataTypeService; _previewDefault = previewDefault; @@ -38,11 +42,10 @@ namespace Umbraco.Web.PublishedCache.NuCache // : (T) cache.GetCacheItem(cacheKey); //} - private static T GetCacheItem(string cacheKey, Func getCacheItem) + private T GetCacheItem(string cacheKey, Func getCacheItem) where T : class { - var facade = Facade.Current; - var cache = facade == null ? null : facade.FacadeCache; + var cache = _facadeCache; return cache == null ? getCacheItem() : cache.GetCacheItem(cacheKey, getCacheItem); @@ -68,14 +71,14 @@ namespace Umbraco.Web.PublishedCache.NuCache var member = _memberService.GetById(memberId); return member == null ? null - : PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault); + : PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _facadeAccessor); }); } private IPublishedContent /*IPublishedMember*/ GetById(IMember member, bool previewing) { return GetCacheItem(CacheKeys.MemberCacheMember("ById", _previewDefault, member.Id), () => - PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing)); + PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing, _facadeAccessor)); } public IPublishedContent /*IPublishedMember*/ GetByProviderKey(object key) @@ -110,7 +113,7 @@ namespace Umbraco.Web.PublishedCache.NuCache public IPublishedContent /*IPublishedMember*/ GetByMember(IMember member) { - return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault); + return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _facadeAccessor); } public IEnumerable GetAtRoot(bool preview) @@ -118,7 +121,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // because members are flat (not a tree) everything is at root // because we're loading everything... let's just not cache? var members = _memberService.GetAllMembers(); - return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview)); + return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview, _facadeAccessor)); } public XPathNavigator CreateNavigator() diff --git a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs index e4668aa731..71fd6fae94 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs @@ -11,6 +11,7 @@ namespace Umbraco.Web.PublishedCache.NuCache [XmlType(Namespace = "http://umbraco.org/webservices/")] class Property : PublishedPropertyBase { + private readonly IFacadeAccessor _facadeAccessor; private readonly object _dataValue; private readonly Guid _contentUid; private readonly bool _isPreviewing; @@ -23,12 +24,12 @@ namespace Umbraco.Web.PublishedCache.NuCache private string _recurseCacheKey; // initializes a published content property with no value - public Property(PublishedPropertyType propertyType, PublishedContent content) - : this(propertyType, content, null) + public Property(PublishedPropertyType propertyType, PublishedContent content, IFacadeAccessor facadeAccessor) + : this(propertyType, content, null, facadeAccessor) { } // initializes a published content property with a value - public Property(PublishedPropertyType propertyType, PublishedContent content, object valueSource) + public Property(PublishedPropertyType propertyType, PublishedContent content, object valueSource, IFacadeAccessor facadeAccessor) : base(propertyType) { _dataValue = valueSource; @@ -36,6 +37,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var inner = PublishedContent.UnwrapIPublishedContent(content); _isPreviewing = inner.IsPreviewing; _isMember = content.ContentType.ItemType == PublishedItemType.Member; + _facadeAccessor = facadeAccessor; } // clone for previewing as draft a published content that is published and has no draft @@ -46,6 +48,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentUid = origin._contentUid; _isPreviewing = true; _isMember = origin._isMember; + _facadeAccessor = origin._facadeAccessor; } // detached @@ -58,10 +61,8 @@ namespace Umbraco.Web.PublishedCache.NuCache // _isMember = isMember; //} - public override bool HasValue - { - get { return _dataValue != null && ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false); } - } + public override bool HasValue => _dataValue != null + && ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false); private class ValueSet { @@ -73,15 +74,11 @@ namespace Umbraco.Web.PublishedCache.NuCache public object XPath; } - internal string RecurseCacheKey - { - get { return _recurseCacheKey ?? (_recurseCacheKey = CacheKeys.PropertyRecurse(_contentUid, PropertyTypeAlias, _isPreviewing)); } - } + internal string RecurseCacheKey => _recurseCacheKey + ?? (_recurseCacheKey = CacheKeys.PropertyRecurse(_contentUid, PropertyTypeAlias, _isPreviewing)); - internal string ValueSetCacheKey - { - get { return _valueSetCacheKey ?? (_valueSetCacheKey = CacheKeys.PropertyValueSet(_contentUid, PropertyTypeAlias, _isPreviewing)); } - } + internal string ValueSetCacheKey => _valueSetCacheKey + ?? (_valueSetCacheKey = CacheKeys.PropertyValueSet(_contentUid, PropertyTypeAlias, _isPreviewing)); private ValueSet GetValueSet(PropertyCacheLevel cacheLevel) { @@ -103,7 +100,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // snapshot cache (if we don't want to pollute the snapshot cache with short-lived // data) depending on settings // for members, always cache in the facade cache - never pollute snapshot cache - facade = Facade.Current; + facade = (Facade) _facadeAccessor.Facade; cache = facade == null ? null : ((_isPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (_isMember == false) @@ -113,8 +110,8 @@ namespace Umbraco.Web.PublishedCache.NuCache break; case PropertyCacheLevel.Request: // cache within the facade cache - facade = Facade.Current; - cache = facade == null ? null : facade.FacadeCache; + facade = (Facade)_facadeAccessor.Facade; + cache = facade?.FacadeCache; valueSet = GetValueSet(cache); break; default: @@ -141,10 +138,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return valueSet.Source; } - public override object DataValue - { - get { return _dataValue; } - } + public override object DataValue => _dataValue; public override object Value { diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 2c37b675b3..7ed0eb9dcb 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -12,30 +12,29 @@ namespace Umbraco.Web.PublishedCache.NuCache { internal class PublishedContent : PublishedContentWithKeyBase { + private readonly IFacadeAccessor _facadeAccessor; private readonly ContentNode _contentNode; // ReSharper disable once InconsistentNaming internal readonly ContentData _contentData; // internal for ContentNode cloning - private readonly IPublishedProperty[] _properties; private readonly string _urlName; - private readonly bool _isPreviewing; #region Constructors - public PublishedContent(ContentNode contentNode, ContentData contentData) + public PublishedContent(ContentNode contentNode, ContentData contentData, IFacadeAccessor facadeAccessor) { _contentNode = contentNode; _contentData = contentData; + _facadeAccessor = facadeAccessor; _urlName = _contentData.Name.ToUrlSegment(); - _isPreviewing = _contentData.Published == false; - _properties = CreateProperties(this, contentData.Properties); + IsPreviewing = _contentData.Published == false; + PropertiesArray = CreateProperties(this, contentData.Properties); } - private static string GetProfileNameById(int id) + private string GetProfileNameById(int id) { - var facade = Facade.Current; - var cache = facade == null ? null : facade.FacadeCache; + var cache = GetCurrentFacadeCache(); return cache == null ? GetProfileNameByIdNoCache(id) : (string) cache.GetCacheItem(CacheKeys.ProfileName(id), () => GetProfileNameByIdNoCache(id)); @@ -45,8 +44,8 @@ namespace Umbraco.Web.PublishedCache.NuCache { #if DEBUG var context = ApplicationContext.Current; - var servicesContext = context == null ? null : context.Services; - var userService = servicesContext == null ? null : servicesContext.UserService; + var servicesContext = context?.Services; + var userService = servicesContext?.UserService; if (userService == null) return "[null]"; // for tests #else // we don't want each published content to hold a reference to the service @@ -54,10 +53,10 @@ namespace Umbraco.Web.PublishedCache.NuCache var userService = ApplicationContext.Current.Services.UserService; #endif var user = userService.GetProfileById(id); - return user == null ? null : user.Name; + return user?.Name; } - private static IPublishedProperty[] CreateProperties(PublishedContent content, IDictionary values) + private IPublishedProperty[] CreateProperties(PublishedContent content, IDictionary values) { return content._contentNode.ContentType .PropertyTypes @@ -65,38 +64,40 @@ namespace Umbraco.Web.PublishedCache.NuCache { object value; return values.TryGetValue(propertyType.PropertyTypeAlias, out value) - ? (IPublishedProperty) new Property(propertyType, content, value) - : (IPublishedProperty) new Property(propertyType, content); + ? new Property(propertyType, content, value, _facadeAccessor) as IPublishedProperty + : new Property(propertyType, content, _facadeAccessor) as IPublishedProperty; }) .ToArray(); } // (see ContentNode.CloneParent) - public PublishedContent(ContentNode contentNode, PublishedContent origin) + public PublishedContent(ContentNode contentNode, PublishedContent origin, IFacadeAccessor facadeAccessor) { _contentNode = contentNode; + _facadeAccessor = facadeAccessor; _contentData = origin._contentData; _urlName = origin._urlName; - _isPreviewing = origin._isPreviewing; + IsPreviewing = origin.IsPreviewing; // here is the main benefit: we do not re-create properties so if anything // is cached locally, we share the cache - which is fine - if anything depends // on the tree structure, it should not be cached locally to begin with - _properties = origin._properties; + PropertiesArray = origin.PropertiesArray; } // clone for previewing as draft a published content that is published and has no draft - private PublishedContent(PublishedContent origin) + private PublishedContent(PublishedContent origin, IFacadeAccessor facadeAccessor) { + _facadeAccessor = facadeAccessor; _contentNode = origin._contentNode; _contentData = origin._contentData; _urlName = origin._urlName; - _isPreviewing = true; + IsPreviewing = true; // clone properties so _isPreviewing is true - _properties = origin._properties.Select(x => (IPublishedProperty) new Property((Property) x)).ToArray(); + PropertiesArray = origin.PropertiesArray.Select(x => (IPublishedProperty) new Property((Property) x)).ToArray(); } #endregion @@ -128,14 +129,14 @@ namespace Umbraco.Web.PublishedCache.NuCache } } - private static IPublishedContent GetContentById(bool previewing, int id) + private IPublishedContent GetContentById(bool previewing, int id) { - return _getContentByIdFunc(Facade.Current, previewing, id); + return _getContentByIdFunc(_facadeAccessor.Facade, previewing, id); } - private static IEnumerable GetContentByIds(bool previewing, IEnumerable ids) + private IEnumerable GetContentByIds(bool previewing, IEnumerable ids) { - var facade = Facade.Current; + var facade = _facadeAccessor.Facade; // beware! the loop below CANNOT be converted to query such as: //return ids.Select(x => _getContentByIdFunc(facade, previewing, x)).Where(x => x != null); @@ -151,14 +152,14 @@ namespace Umbraco.Web.PublishedCache.NuCache } } - private static IPublishedContent GetMediaById(bool previewing, int id) + private IPublishedContent GetMediaById(bool previewing, int id) { - return _getMediaByIdFunc(Facade.Current, previewing, id); + return _getMediaByIdFunc(_facadeAccessor.Facade, previewing, id); } - private static IEnumerable GetMediaByIds(bool previewing, IEnumerable ids) + private IEnumerable GetMediaByIds(bool previewing, IEnumerable ids) { - var facade = Facade.Current; + var facade = _facadeAccessor.Facade; // see note above for content @@ -174,42 +175,30 @@ namespace Umbraco.Web.PublishedCache.NuCache #region IPublishedContent - public override int Id { get { return _contentNode.Id; } } - public override Guid Key { get { return _contentNode.Uid; } } - public override int DocumentTypeId { get { return _contentNode.ContentType.Id; } } - public override string DocumentTypeAlias { get { return _contentNode.ContentType.Alias; } } - public override PublishedItemType ItemType { get { return _contentNode.ContentType.ItemType; } } + public override int Id => _contentNode.Id; + public override Guid Key => _contentNode.Uid; + public override int DocumentTypeId => _contentNode.ContentType.Id; + public override string DocumentTypeAlias => _contentNode.ContentType.Alias; + public override PublishedItemType ItemType => _contentNode.ContentType.ItemType; - public override string Name { get { return _contentData.Name; } } - public override int Level { get { return _contentNode.Level; } } - public override string Path { get { return _contentNode.Path; } } - public override int SortOrder { get { return _contentNode.SortOrder; } } - public override Guid Version { get { return _contentData.Version; } } - public override int TemplateId { get { return _contentData.TemplateId; } } + public override string Name => _contentData.Name; + public override int Level => _contentNode.Level; + public override string Path => _contentNode.Path; + public override int SortOrder => _contentNode.SortOrder; + public override Guid Version => _contentData.Version; + public override int TemplateId => _contentData.TemplateId; - public override string UrlName { get { return _urlName; } } + public override string UrlName => _urlName; - public override DateTime CreateDate { get { return _contentNode.CreateDate; } } - public override DateTime UpdateDate { get { return _contentData.VersionDate; } } + public override DateTime CreateDate => _contentNode.CreateDate; + public override DateTime UpdateDate => _contentData.VersionDate; - public override int CreatorId { get { return _contentNode.CreatorId; } } - public override string CreatorName { get { return GetProfileNameById(_contentNode.CreatorId); } } - public override int WriterId { get { return _contentData.WriterId; } } - public override string WriterName { get { return GetProfileNameById(_contentData.WriterId); } } + public override int CreatorId => _contentNode.CreatorId; + public override string CreatorName => GetProfileNameById(_contentNode.CreatorId); + public override int WriterId => _contentData.WriterId; + public override string WriterName => GetProfileNameById(_contentData.WriterId); - public override bool IsDraft { get { return _contentData.Published == false; } } - - // beware what you use that one for - you don't want to cache its result - private ICacheProvider GetAppropriateFacadeCache() - { - var facade = Facade.Current; - var cache = facade == null - ? null - : ((_isPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (ItemType != PublishedItemType.Member) - ? facade.SnapshotCache - : facade.FacadeCache); - return cache; - } + public override bool IsDraft => _contentData.Published == false; public override IPublishedContent Parent { @@ -220,9 +209,9 @@ namespace Umbraco.Web.PublishedCache.NuCache switch (_contentNode.ContentType.ItemType) { case PublishedItemType.Content: - return GetContentById(_isPreviewing, _contentNode.ParentContentId); + return GetContentById(IsPreviewing, _contentNode.ParentContentId); case PublishedItemType.Media: - return GetMediaById(_isPreviewing, _contentNode.ParentContentId); + return GetMediaById(IsPreviewing, _contentNode.ParentContentId); default: throw new Exception("oops"); } @@ -231,16 +220,13 @@ namespace Umbraco.Web.PublishedCache.NuCache private string _childrenCacheKey; - private string ChildrenCacheKey - { - get { return _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, _isPreviewing)); } - } + private string ChildrenCacheKey => _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, IsPreviewing)); public override IEnumerable Children { get { - var cache = GetAppropriateFacadeCache(); + var cache = GetAppropriateCurrentFacadeCache(); if (cache == null || FacadeService.CachePublishedContentChildren == false) return GetChildren(); @@ -255,10 +241,10 @@ namespace Umbraco.Web.PublishedCache.NuCache switch (_contentNode.ContentType.ItemType) { case PublishedItemType.Content: - c = GetContentByIds(_isPreviewing, _contentNode.ChildContentIds); + c = GetContentByIds(IsPreviewing, _contentNode.ChildContentIds); break; case PublishedItemType.Media: - c = GetMediaByIds(_isPreviewing, _contentNode.ChildContentIds); + c = GetMediaByIds(IsPreviewing, _contentNode.ChildContentIds); break; default: throw new Exception("oops"); @@ -272,12 +258,12 @@ namespace Umbraco.Web.PublishedCache.NuCache // Q: perfs-wise, is it better than having the store managed an ordered list } - public override ICollection Properties { get { return _properties; } } + public override ICollection Properties => PropertiesArray; public override IPublishedProperty GetProperty(string alias) { var index = _contentNode.ContentType.GetPropertyIndex(alias); - var property = index < 0 ? null : _properties[index]; + var property = index < 0 ? null : PropertiesArray[index]; return property; } @@ -286,7 +272,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var property = GetProperty(alias); if (recurse == false) return property; - var cache = GetAppropriateFacadeCache(); + var cache = GetAppropriateCurrentFacadeCache(); if (cache == null) return base.GetProperty(alias, true); @@ -294,9 +280,28 @@ namespace Umbraco.Web.PublishedCache.NuCache return (Property) cache.GetCacheItem(key, () => base.GetProperty(alias, true)); } - public override PublishedContentType ContentType + public override PublishedContentType ContentType => _contentNode.ContentType; + + #endregion + + #region Caching + + // beware what you use that one for - you don't want to cache its result + private ICacheProvider GetAppropriateCurrentFacadeCache() { - get { return _contentNode.ContentType; } + var facade = (Facade) _facadeAccessor.Facade; + var cache = facade == null + ? null + : ((IsPreviewing == false || FacadeService.FullCacheWhenPreviewing) && (ItemType != PublishedItemType.Member) + ? facade.SnapshotCache + : facade.FacadeCache); + return cache; + } + + private ICacheProvider GetCurrentFacadeCache() + { + var facade = (Facade) _facadeAccessor.Facade; + return facade?.FacadeCache; } #endregion @@ -304,38 +309,35 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Internal // used by navigable content - internal IPublishedProperty[] PropertiesArray { get { return _properties; } } + internal IPublishedProperty[] PropertiesArray { get; } // used by navigable content - internal int ParentId { get { return _contentNode.ParentContentId; } } + internal int ParentId => _contentNode.ParentContentId; // used by navigable content // includes all children, published or unpublished // NavigableNavigator takes care of selecting those it wants - internal IList ChildIds { get { return _contentNode.ChildContentIds; } } + internal IList ChildIds => _contentNode.ChildContentIds; // used by Property // gets a value indicating whether the content or media exists in // a previewing context or not, ie whether its Parent, Children, and // properties should refer to published, or draft content - internal bool IsPreviewing { get { return _isPreviewing; } } + internal bool IsPreviewing { get; } private string _asPreviewingCacheKey; - private string AsPreviewingCacheKey - { - get { return _asPreviewingCacheKey ?? (_asPreviewingCacheKey = CacheKeys.PublishedContentAsPreviewing(Key)); } - } + private string AsPreviewingCacheKey => _asPreviewingCacheKey ?? (_asPreviewingCacheKey = CacheKeys.PublishedContentAsPreviewing(Key)); // used by ContentCache internal IPublishedContent AsPreviewingModel() { - if (_isPreviewing) + if (IsPreviewing) return this; - var cache = GetAppropriateFacadeCache(); - if (cache == null) return new PublishedContent(this).CreateModel(); - return (IPublishedContent) cache.GetCacheItem(AsPreviewingCacheKey, () => new PublishedContent(this).CreateModel()); + var cache = GetAppropriateCurrentFacadeCache(); + if (cache == null) return new PublishedContent(this, _facadeAccessor).CreateModel(); + return (IPublishedContent) cache.GetCacheItem(AsPreviewingCacheKey, () => new PublishedContent(this, _facadeAccessor).CreateModel()); } // used by Navigable.Source,... diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedMember.cs index c1c635a8bf..77b50213a7 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedMember.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedMember.cs @@ -17,13 +17,13 @@ namespace Umbraco.Web.PublishedCache.NuCache { private readonly IMember _member; - private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData) - : base(contentNode, contentData) + private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData, IFacadeAccessor facadeAccessor) + : base(contentNode, contentData, facadeAccessor) { _member = member; } - public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing) + public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing, IFacadeAccessor facadeAccessor) { var d = new ContentData { @@ -40,7 +40,7 @@ namespace Umbraco.Web.PublishedCache.NuCache member.Level, member.Path, member.SortOrder, member.ParentId, member.CreateDate, member.CreatorId); - return new PublishedMember(member, n, d).CreateModel(); + return new PublishedMember(member, n, d, facadeAccessor).CreateModel(); } private static Dictionary GetPropertyValues(PublishedContentType contentType, IMember member) diff --git a/src/Umbraco.Web/PublishedCache/UmbracoContextFacadeAccessor.cs b/src/Umbraco.Web/PublishedCache/UmbracoContextFacadeAccessor.cs new file mode 100644 index 0000000000..f8feca4e54 --- /dev/null +++ b/src/Umbraco.Web/PublishedCache/UmbracoContextFacadeAccessor.cs @@ -0,0 +1,29 @@ +using System; + +namespace Umbraco.Web.PublishedCache +{ + public class UmbracoContextFacadeAccessor : IFacadeAccessor + { + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + + public UmbracoContextFacadeAccessor(IUmbracoContextAccessor umbracoContextAccessor) + { + _umbracoContextAccessor = umbracoContextAccessor; + } + + public IFacade Facade + { + get + { + var umbracoContext = _umbracoContextAccessor.UmbracoContext; + if (umbracoContext == null) throw new Exception("The IUmbracoContextAccessor could not provide an UmbracoContext."); + return umbracoContext.Facade; + } + + set + { + throw new NotSupportedException(); // not ok to set + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/Facade.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/Facade.cs index 0b2f331b14..8e773a85e7 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/Facade.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/Facade.cs @@ -40,17 +40,5 @@ /// Gets the . /// public IDomainCache DomainCache { get; } - - public static void ResyncCurrent() - { - if (FacadeServiceResolver.HasCurrent == false) return; - var service = FacadeServiceResolver.Current.Service as FacadeService; - var facade = service?.GetFacade() as Facade; - if (facade == null) return; - ((PublishedContentCache) facade.ContentCache).Resync(); - ((PublishedMediaCache)facade.MediaCache).Resync(); - - // not trying to resync members or domains, which are not cached really - } } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs index 273daa860c..f40f27f7b9 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs @@ -32,31 +32,35 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IDatabaseUnitOfWorkProvider uowProvider, ICacheProvider requestCache, IEnumerable segmentProviders, + IFacadeAccessor facadeAccessor, bool testing = false, bool enableRepositoryEvents = true) - : this(serviceContext, uowProvider, requestCache, segmentProviders, null, testing, enableRepositoryEvents) + : this(serviceContext, uowProvider, requestCache, segmentProviders, facadeAccessor, null, testing, enableRepositoryEvents) { } // used in some tests internal FacadeService(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, ICacheProvider requestCache, + IFacadeAccessor facadeAccessor, PublishedContentTypeCache contentTypeCache, bool testing, bool enableRepositoryEvents) - : this(serviceContext, uowProvider, requestCache, Enumerable.Empty(), contentTypeCache, testing, enableRepositoryEvents) + : this(serviceContext, uowProvider, requestCache, Enumerable.Empty(), facadeAccessor, contentTypeCache, testing, enableRepositoryEvents) { } private FacadeService(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, ICacheProvider requestCache, IEnumerable segmentProviders, + IFacadeAccessor facadeAccessor, PublishedContentTypeCache contentTypeCache, bool testing, bool enableRepositoryEvents) + : base(facadeAccessor) { _routesCache = new RoutesCache(); _contentTypeCache = contentTypeCache ?? new PublishedContentTypeCache(serviceContext.ContentTypeService, serviceContext.MediaTypeService, serviceContext.MemberTypeService); - _xmlStore = new XmlStore(serviceContext, uowProvider, _routesCache, _contentTypeCache, segmentProviders, testing, enableRepositoryEvents); + _xmlStore = new XmlStore(serviceContext, uowProvider, _routesCache, _contentTypeCache, segmentProviders, facadeAccessor, testing, enableRepositoryEvents); _domainService = serviceContext.DomainService; _memberService = serviceContext.MemberService; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs index 4bdb6029b7..bfbf674f40 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs @@ -49,6 +49,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private bool _withRepositoryEvents; private bool _withOtherEvents; + private readonly IFacadeAccessor _facadeAccessor; private readonly PublishedContentTypeCache _contentTypeCache; private readonly RoutesCache _routesCache; private readonly ServiceContext _serviceContext; // fixme WHY @@ -61,15 +62,15 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc. - public XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, IEnumerable segmentProviders) - : this(serviceContext, uowProvider, routesCache, contentTypeCache, segmentProviders, false, false) + public XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, IEnumerable segmentProviders, IFacadeAccessor facadeAccessor) + : this(serviceContext, uowProvider, routesCache, contentTypeCache, segmentProviders, facadeAccessor, false, false) { } // internal for unit tests // no file nor db, no config check // fixme - er, we DO have a DB? internal XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IEnumerable segmentProviders, bool testing, bool enableRepositoryEvents) + IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, bool testing, bool enableRepositoryEvents) { if (testing == false) EnsureConfigurationIsValid(); @@ -78,6 +79,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _uowProvider = uowProvider; _routesCache = routesCache; _contentTypeCache = contentTypeCache; + _facadeAccessor = facadeAccessor; InitializeSerializers(segmentProviders); @@ -1310,7 +1312,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; if (publishedChanged) { safeXml.Commit(); // not auto! - Facade.ResyncCurrent(); + ResyncCurrentFacade(); } } } @@ -1341,7 +1343,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; // ignore media and member types - we're not caching them - Facade.ResyncCurrent(); + ResyncCurrentFacade(); } public void Notify(DataTypeCacheRefresher.JsonPayload[] payloads) @@ -1361,7 +1363,17 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; // ignore media and member types - we're not caching them - Facade.ResyncCurrent(); + ResyncCurrentFacade(); + } + + private void ResyncCurrentFacade() + { + var facade = (Facade) _facadeAccessor.Facade; + if (facade == null) return; + ((PublishedContentCache) facade.ContentCache).Resync(); + ((PublishedMediaCache) facade.MediaCache).Resync(); + + // not trying to resync members or domains, which are not cached really } #endregion diff --git a/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs b/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs index 66beb6e7b0..a874c12832 100644 --- a/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs +++ b/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs @@ -43,14 +43,14 @@ namespace Umbraco.Web.Security.Identity /// string ICookieManager.GetRequestCookie(IOwinContext context, string key) { - if (_umbracoContextAccessor.Value == null || context.Request.Uri.IsClientSideRequest()) + if (_umbracoContextAccessor.UmbracoContext == null || context.Request.Uri.IsClientSideRequest()) { return null; } return ShouldAuthenticateRequest( context, - _umbracoContextAccessor.Value.OriginalRequestUrl) == false + _umbracoContextAccessor.UmbracoContext.OriginalRequestUrl) == false //Don't auth request, don't return a cookie ? null //Return the default implementation @@ -73,8 +73,8 @@ namespace Umbraco.Web.Security.Identity /// internal bool ShouldAuthenticateRequest(IOwinContext ctx, Uri originalRequestUrl, bool checkForceAuthTokens = true) { - if (_umbracoContextAccessor.Value.Application.IsConfigured == false - && _umbracoContextAccessor.Value.Application.DatabaseContext.IsDatabaseConfigured == false) + if (_umbracoContextAccessor.UmbracoContext.Application.IsConfigured == false + && _umbracoContextAccessor.UmbracoContext.Application.DatabaseContext.IsDatabaseConfigured == false) { //Do not authenticate the request if we don't have a db and we are not configured - since we will never need // to know a current user in this scenario - we treat it as a new install. Without this we can have some issues diff --git a/src/Umbraco.Web/Security/Identity/ForceRenewalCookieAuthenticationHandler.cs b/src/Umbraco.Web/Security/Identity/ForceRenewalCookieAuthenticationHandler.cs index c7030b2558..c1026de7df 100644 --- a/src/Umbraco.Web/Security/Identity/ForceRenewalCookieAuthenticationHandler.cs +++ b/src/Umbraco.Web/Security/Identity/ForceRenewalCookieAuthenticationHandler.cs @@ -54,7 +54,7 @@ namespace Umbraco.Web.Security.Identity /// protected override Task ApplyResponseGrantAsync() { - if (_umbracoContextAccessor.Value == null || Context.Request.Uri.IsClientSideRequest()) + if (_umbracoContextAccessor.UmbracoContext == null || Context.Request.Uri.IsClientSideRequest()) { return Task.FromResult(0); } @@ -63,7 +63,7 @@ namespace Umbraco.Web.Security.Identity // which means that it is not a normal URL that is authenticated. var normalAuthUrl = ((BackOfficeCookieManager) Options.CookieManager) - .ShouldAuthenticateRequest(Context, _umbracoContextAccessor.Value.OriginalRequestUrl, + .ShouldAuthenticateRequest(Context, _umbracoContextAccessor.UmbracoContext.OriginalRequestUrl, //Pass in false, we want to know if this is a normal auth'd page checkForceAuthTokens: false); //This is auth'd normally, so OWIN will naturally take care of the cookie renewal diff --git a/src/Umbraco.Web/SingletonUmbracoContextAccessor.cs b/src/Umbraco.Web/SingletonUmbracoContextAccessor.cs index ef2df5b6ea..239af8ccb7 100644 --- a/src/Umbraco.Web/SingletonUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/SingletonUmbracoContextAccessor.cs @@ -2,9 +2,6 @@ namespace Umbraco.Web { internal class SingletonUmbracoContextAccessor : IUmbracoContextAccessor { - public UmbracoContext Value - { - get { return UmbracoContext.Current; } - } + public UmbracoContext UmbracoContext => UmbracoContext.Current; } } \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 2b79b3d7d0..1d51a23247 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -159,6 +159,7 @@ + @@ -211,6 +212,7 @@ + @@ -240,6 +242,7 @@ + @@ -261,6 +264,9 @@ + + ASPXCodeBehind + diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 0abe9672ee..d705fffb5a 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -325,12 +325,15 @@ namespace Umbraco.Web { base.ConfigureCoreServices(container); + // configure the temp. Current + Current.Container = container; + //ModelMappers container.RegisterFrom(); container.EnablePerWebRequestScope(); - //no need to declare as per request, it's lifetime is already managed as a singleton + // no need to declare as per request, it's lifetime is already managed as a singleton container.Register(factory => new HttpContextWrapper(HttpContext.Current)); container.RegisterSingleton(); @@ -345,6 +348,7 @@ namespace Umbraco.Web factory.GetInstance().MainDom, factory.GetInstance(), factory.GetInstance(), + new UmbracoContextFacadeAccessor(new SingletonUmbracoContextAccessor()), // fixme inject! factory.GetInstance())); //no need to declare as per request, currently we manage it's lifetime as the singleton diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index 39ca2524c4..e148e45337 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -1263,10 +1263,9 @@ namespace umbraco } else { - // FIXME inject! - var caches = FacadeServiceResolver.Current.Service.GetFacade() + var facade = Umbraco.Web.Current.Facade ?? FacadeServiceResolver.Current.Service.CreateFacade(null); - contentCache = caches.ContentCache as PublishedContentCache; + contentCache = facade.ContentCache as PublishedContentCache; } if (contentCache == null) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/endPreview.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/endPreview.aspx.cs new file mode 100644 index 0000000000..a1a57d7fec --- /dev/null +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/endPreview.aspx.cs @@ -0,0 +1,35 @@ +using System; +using System.Web; +using System.Web.UI; +using Umbraco.Core; +using Umbraco.Web; +using Umbraco.Web.PublishedCache; + +namespace umbraco.presentation +{ + public class endPreview : Page + { + protected void Page_Load(object sender, EventArgs e) + { + var request = (new HttpRequestWrapper(Request)); + + var previewToken = request.GetPreviewCookieValue(); + var service = FacadeServiceResolver.Current.Service; + service.ExitPreview(previewToken); + + HttpContext.Current.ExpireCookie(Constants.Web.PreviewCookieName); + + var redir = Request.QueryString["redir"]; + Uri url = null; + + if (Uri.IsWellFormedUriString(redir, UriKind.Relative) == false + || redir.StartsWith("//") + || Uri.TryCreate(redir, UriKind.Relative, out url) == false) + { + Response.Redirect("/", true); + } + + Response.Redirect(url.ToString(), true); + } + } +} \ No newline at end of file