using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Web; using System.Web.Hosting; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; namespace Umbraco.Web { /// /// Creates and manages instances. /// public class UmbracoContextFactory : IUmbracoContextFactory { private static readonly NullWriter NullWriterInstance = new NullWriter(); private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; private readonly IUmbracoSettingsSection _umbracoSettings; private readonly IGlobalSettings _globalSettings; private readonly UrlProviderCollection _urlProviders; private readonly MediaUrlProviderCollection _mediaUrlProviders; private readonly IUserService _userService; /// /// Initializes a new instance of the class. /// public UmbracoContextFactory(IUmbracoContextAccessor umbracoContextAccessor, IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IUserService userService) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _defaultCultureAccessor = defaultCultureAccessor ?? throw new ArgumentNullException(nameof(defaultCultureAccessor)); _umbracoSettings = umbracoSettings ?? throw new ArgumentNullException(nameof(umbracoSettings)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); _urlProviders = urlProviders ?? throw new ArgumentNullException(nameof(urlProviders)); _mediaUrlProviders = mediaUrlProviders ?? throw new ArgumentNullException(nameof(mediaUrlProviders)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); } private UmbracoContext CreateUmbracoContext(HttpContextBase httpContext) { // make sure we have a variation context if (_variationContextAccessor.VariationContext == null) { // TODO: By using _defaultCultureAccessor.DefaultCulture this means that the VariationContext will always return a variant culture, it will never // return an empty string signifying that the culture is invariant. But does this matter? Are we actually expecting this to return an empty string // for invariant routes? From what i can tell throughout the codebase is that whenever we are checking against the VariationContext.Culture we are // also checking if the content type varies by culture or not. This is fine, however the code in the ctor of VariationContext is then misleading // since it's assuming that the Culture can be empty (invariant) when in reality of a website this will never be empty since a real culture is always set here. _variationContextAccessor.VariationContext = new VariationContext(_defaultCultureAccessor.DefaultCulture); } var webSecurity = new WebSecurity(httpContext, _userService, _globalSettings); return new UmbracoContext(httpContext, _publishedSnapshotService, webSecurity, _umbracoSettings, _urlProviders, _mediaUrlProviders, _globalSettings, _variationContextAccessor); } /// public UmbracoContextReference EnsureUmbracoContext(HttpContextBase httpContext = null) { var currentUmbracoContext = _umbracoContextAccessor.UmbracoContext; if (currentUmbracoContext != null) return new UmbracoContextReference(currentUmbracoContext, false, _umbracoContextAccessor); httpContext = httpContext ?? new HttpContextWrapper(HttpContext.Current ?? new HttpContext(new SimpleWorkerRequest("null.aspx", "", NullWriterInstance))); var umbracoContext = CreateUmbracoContext(httpContext); _umbracoContextAccessor.UmbracoContext = umbracoContext; return new UmbracoContextReference(umbracoContext, true, _umbracoContextAccessor); } // dummy TextWriter that does not write private class NullWriter : TextWriter { public override Encoding Encoding => Encoding.UTF8; } } }