diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index 2e42681399..86bec52b69 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -32,11 +32,12 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters => PropertyCacheLevel.Snapshot; public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (IPublishedContent); + => typeof(IPublishedContent); public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) { - if (source == null) return null; + if (source == null) + return null; var attemptConvertInt = source.TryConvertTo(); if (attemptConvertInt.Success) @@ -54,43 +55,44 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters return null; } - if (_umbracoContextAccessor.UmbracoContext != null) + + + IPublishedContent member; + + if (!_publishedSnapshotAccessor.TryGetPublishedSnapshot(out var publishedSnapshot)) { - IPublishedContent member; - if (!_publishedSnapshotAccessor.TryGetPublishedSnapshot(out var publishedSnapshot)) + throw new InvalidOperationException("Wasn't possible to a get a valid Snapshot"); + } + if (source is int id) + { + IMember m = _memberService.GetById(id); + if (m == null) { - throw new InvalidOperationException("Wasn't possible to a get a valid Snapshot"); + return null; } - if (source is int id) + member = publishedSnapshot.Members.Get(m); + if (member != null) { - IMember m = _memberService.GetById(id); - if (m == null) - { - return null; - } - member = publishedSnapshot.Members.Get(m); - if (member != null) - { - return member; - } + return member; } - else + } + else + { + var sourceUdi = source as GuidUdi; + if (sourceUdi == null) + return null; + + IMember m = _memberService.GetByKey(sourceUdi.Guid); + if (m == null) { - var sourceUdi = source as GuidUdi; - if (sourceUdi == null) return null; + return null; + } - IMember m = _memberService.GetByKey(sourceUdi.Guid); - if (m == null) - { - return null; - } + member = publishedSnapshot.Members.Get(m); - member = publishedSnapshot.Members.Get(m); - - if (member != null) - { - return member; - } + if (member != null) + { + return member; } } diff --git a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs index 8ab6fab7d9..4d8c823b6a 100644 --- a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs +++ b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs @@ -21,8 +21,11 @@ namespace Umbraco.Cms.Core.PublishedCache { get { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; - return umbracoContext?.PublishedSnapshot; + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + return null; + } + return umbracoContext.PublishedSnapshot; } set => throw new NotSupportedException(); // not ok to set @@ -30,7 +33,12 @@ namespace Umbraco.Cms.Core.PublishedCache public bool TryGetPublishedSnapshot(out IPublishedSnapshot publishedSnapshot) { - publishedSnapshot = _umbracoContextAccessor.UmbracoContext?.PublishedSnapshot; + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + publishedSnapshot = null; + return false; + } + publishedSnapshot = umbracoContext.PublishedSnapshot; return publishedSnapshot is not null; } diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs index 6ef6348de8..ab0f940543 100644 --- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs @@ -58,7 +58,10 @@ namespace Umbraco.Cms.Core.Routing /// public IEnumerable GetOtherUrls(int id, Uri current) { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } var node = umbracoContext.Content.GetById(id); if (node == null) yield break; diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs index a64d59261a..13a3d8c973 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs @@ -41,8 +41,11 @@ namespace Umbraco.Cms.Core.Routing /// A value indicating whether an Umbraco document was found and assigned. public bool TryFindContent(IPublishedRequestBuilder frequest) { - IUmbracoContext umbCtx = _umbracoContextAccessor.UmbracoContext; - if (umbCtx == null || (umbCtx != null && umbCtx.InPreviewMode == false && _webRoutingSettings.DisableFindContentByIdPath)) + if(!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + return false; + } + if (umbracoContext == null || (umbracoContext != null && umbracoContext.InPreviewMode == false && _webRoutingSettings.DisableFindContentByIdPath)) { return false; } @@ -65,7 +68,7 @@ namespace Umbraco.Cms.Core.Routing if (nodeId > 0) { _logger.LogDebug("Id={NodeId}", nodeId); - node = umbCtx.Content.GetById(nodeId); + node = umbracoContext.Content.GetById(nodeId); if (node != null) { diff --git a/src/Umbraco.Core/Routing/ContentFinderByRedirectUrl.cs b/src/Umbraco.Core/Routing/ContentFinderByRedirectUrl.cs index 93448c02cf..a47fa34e96 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByRedirectUrl.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByRedirectUrl.cs @@ -45,8 +45,7 @@ namespace Umbraco.Cms.Core.Routing /// Optionally, can also assign the template or anything else on the document request, although that is not required. public bool TryFindContent(IPublishedRequestBuilder frequest) { - IUmbracoContext umbCtx = _umbracoContextAccessor.UmbracoContext; - if (umbCtx == null) + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) { return false; } @@ -63,7 +62,7 @@ namespace Umbraco.Cms.Core.Routing return false; } - IPublishedContent content = umbCtx.Content.GetById(redirectUrl.ContentId); + IPublishedContent content = umbracoContext.Content.GetById(redirectUrl.ContentId); var url = content == null ? "#" : content.Url(_publishedUrlProvider, redirectUrl.Culture); if (url.StartsWith("#")) { diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrl.cs b/src/Umbraco.Core/Routing/ContentFinderByUrl.cs index 4f08e5aa49..9174ed999a 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrl.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrl.cs @@ -35,8 +35,7 @@ namespace Umbraco.Cms.Core.Routing /// A value indicating whether an Umbraco document was found and assigned. public virtual bool TryFindContent(IPublishedRequestBuilder frequest) { - IUmbracoContext umbCtx = UmbracoContextAccessor.UmbracoContext; - if (umbCtx == null) + if (!UmbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) { return false; } @@ -61,8 +60,7 @@ namespace Umbraco.Cms.Core.Routing /// The document node, or null. protected IPublishedContent FindContent(IPublishedRequestBuilder docreq, string route) { - IUmbracoContext umbCtx = UmbracoContextAccessor.UmbracoContext; - if (umbCtx == null) + if (!UmbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) { return null; } @@ -74,7 +72,7 @@ namespace Umbraco.Cms.Core.Routing _logger.LogDebug("Test route {Route}", route); - IPublishedContent node = umbCtx.Content.GetByRoute(umbCtx.InPreviewMode, route, culture: docreq.Culture); + IPublishedContent node = umbracoContext.Content.GetByRoute(umbracoContext.InPreviewMode, route, culture: docreq.Culture); if (node != null) { docreq.SetPublishedContent(node); diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index c3f294fbdb..3ebfa7f80b 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Options; @@ -48,9 +48,30 @@ namespace Umbraco.Cms.Core.Routing #region GetUrl - private IPublishedContent GetDocument(int id) => _umbracoContextAccessor.UmbracoContext.Content.GetById(id); - private IPublishedContent GetDocument(Guid id) => _umbracoContextAccessor.UmbracoContext.Content.GetById(id); - private IPublishedContent GetMedia(Guid id) => _umbracoContextAccessor.UmbracoContext.Media.GetById(id); + private IPublishedContent GetDocument(int id) + { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + return umbracoContext.Content.GetById(id); + } + private IPublishedContent GetDocument(Guid id) + { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + return umbracoContext.Content.GetById(id); + } + private IPublishedContent GetMedia(Guid id) + { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + return umbracoContext.Media.GetById(id); + } /// /// Gets the URL of a published content. @@ -106,7 +127,14 @@ namespace Umbraco.Cms.Core.Routing } if (current == null) - current = _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl; + { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + current = umbracoContext.CleanedUmbracoUrl; + } + var url = _urlProviders.Select(provider => provider.GetUrl(content, mode, culture, current)) .FirstOrDefault(u => u != null); @@ -115,10 +143,14 @@ namespace Umbraco.Cms.Core.Routing public string GetUrlFromRoute(int id, string route, string culture) { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } var provider = _urlProviders.OfType().FirstOrDefault(); var url = provider == null ? route // what else? - : provider.GetUrlFromRoute(route, _umbracoContextAccessor.UmbracoContext, id, _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl, Mode, culture)?.Text; + : provider.GetUrlFromRoute(route, umbracoContext, id, umbracoContext.CleanedUmbracoUrl, Mode, culture)?.Text; return url ?? "#"; } @@ -138,7 +170,11 @@ namespace Umbraco.Cms.Core.Routing /// public IEnumerable GetOtherUrls(int id) { - return GetOtherUrls(id, _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl); + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + return GetOtherUrls(id, umbracoContext.CleanedUmbracoUrl); } /// @@ -189,7 +225,8 @@ namespace Umbraco.Cms.Core.Routing /// public string GetMediaUrl(IPublishedContent content, UrlMode mode = UrlMode.Default, string culture = null, string propertyAlias = Constants.Conventions.Media.File, Uri current = null) { - if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); + if (propertyAlias == null) + throw new ArgumentNullException(nameof(propertyAlias)); if (content == null) return ""; @@ -207,7 +244,14 @@ namespace Umbraco.Cms.Core.Routing } if (current == null) - current = _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl; + { + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + current = umbracoContext.CleanedUmbracoUrl; + } + var url = _mediaUrlProviders.Select(provider => provider.GetMediaUrl(content, propertyAlias, mode, culture, current)) diff --git a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs index 12762ee294..bdb221de42 100644 --- a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs +++ b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text.RegularExpressions; using Umbraco.Cms.Core.Routing; @@ -41,13 +41,14 @@ namespace Umbraco.Cms.Core.Templates /// public string EnsureInternalLinks(string text, bool preview) { - if (_umbracoContextAccessor.UmbracoContext == null) + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { throw new InvalidOperationException("Could not parse internal links, there is no current UmbracoContext"); - + } if (!preview) return EnsureInternalLinks(text); - using (_umbracoContextAccessor.UmbracoContext.ForcedPreview(preview)) // force for URL provider + using (umbracoContext.ForcedPreview(preview)) // force for URL provider { return EnsureInternalLinks(text); } @@ -61,9 +62,10 @@ namespace Umbraco.Cms.Core.Templates /// public string EnsureInternalLinks(string text) { - if (_umbracoContextAccessor.UmbracoContext == null) + if (!_umbracoContextAccessor.TryGetUmbracoContext(out _)) + { throw new InvalidOperationException("Could not parse internal links, there is no current UmbracoContext"); - + } foreach((int? intId, GuidUdi udi, string tagValue) in FindLocalLinkIds(text)) { diff --git a/src/Umbraco.Core/Templates/UmbracoComponentRenderer.cs b/src/Umbraco.Core/Templates/UmbracoComponentRenderer.cs index a440876b8f..d2aad81163 100644 --- a/src/Umbraco.Core/Templates/UmbracoComponentRenderer.cs +++ b/src/Umbraco.Core/Templates/UmbracoComponentRenderer.cs @@ -66,8 +66,11 @@ namespace Umbraco.Cms.Core.Templates { throw new ArgumentException("Invalid content id " + contentId); } - - var content = _umbracoContextAccessor.UmbracoContext.Content?.GetById(contentId); + if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext)) + { + throw new InvalidOperationException("A current Umbraco context is not available"); + } + var content = umbracoContext.Content?.GetById(contentId); if (content == null) { diff --git a/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs index 503bb25b57..9dc8f15523 100644 --- a/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs +++ b/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs @@ -17,10 +17,18 @@ namespace Umbraco.Cms.Core.Web /// /// Gets or sets the object. /// + /// public IUmbracoContext UmbracoContext { get => Value; set => Value = value; } + + public bool TryGetUmbracoContext(out IUmbracoContext umbracoContext) + { + umbracoContext = Value; + + return umbracoContext is not null; + } } } diff --git a/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs index 0f15034dd1..a336f47710 100644 --- a/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs +++ b/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core.Web +namespace Umbraco.Cms.Core.Web { /// /// Provides access to UmbracoContext. @@ -6,5 +6,6 @@ public interface IUmbracoContextAccessor { IUmbracoContext UmbracoContext { get; set; } + bool TryGetUmbracoContext(out IUmbracoContext umbracoContext); } } diff --git a/src/Umbraco.PublishedCache.NuCache/Property.cs b/src/Umbraco.PublishedCache.NuCache/Property.cs index dc00b241f7..837fe5717f 100644 --- a/src/Umbraco.PublishedCache.NuCache/Property.cs +++ b/src/Umbraco.PublishedCache.NuCache/Property.cs @@ -142,7 +142,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache // elements cache (if we don't want to pollute the elements cache with short-lived // data) depending on settings // for members, always cache in the snapshot cache - never pollute elements cache - if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out publishedSnapshot)) + if (!_publishedSnapshotAccessor.TryGetPublishedSnapshot(out publishedSnapshot)) { throw new InvalidOperationException("Wasn't possible to a get a valid Snapshot"); } diff --git a/src/Umbraco.Tests.Common/TestUmbracoContextAccessor.cs b/src/Umbraco.Tests.Common/TestUmbracoContextAccessor.cs index 868c3f1806..f9426d1be4 100644 --- a/src/Umbraco.Tests.Common/TestUmbracoContextAccessor.cs +++ b/src/Umbraco.Tests.Common/TestUmbracoContextAccessor.cs @@ -17,5 +17,11 @@ namespace Umbraco.Cms.Tests.Common { UmbracoContext = umbracoContext; } + + public bool TryGetUmbracoContext(out IUmbracoContext umbracoContext) + { + umbracoContext = UmbracoContext; + return umbracoContext is not null; + } } }