Introduced GenericDictionaryRequestAppCache, to use the HttpContext.Items from .NET Core

This commit is contained in:
Bjarke Berg
2020-04-20 06:19:59 +02:00
parent bf1784f9d1
commit c0ec1bf6ca
10 changed files with 280 additions and 131 deletions

View File

@@ -0,0 +1,190 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Implements a fast <see cref="IAppCache"/> on top of HttpContext.Items.
/// </summary>
/// <remarks>
/// <para>If no current HttpContext items can be found (no current HttpContext,
/// or no Items...) then this cache acts as a pass-through and does not cache
/// anything.</para>
/// </remarks>
public class GenericDictionaryRequestAppCache : FastDictionaryAppCacheBase, IRequestCache
{
/// <summary>
/// Initializes a new instance of the <see cref="HttpRequestAppCache"/> class with a context, for unit tests!
/// </summary>
public GenericDictionaryRequestAppCache(Func<IDictionary<object, object>> requestItems) : base()
{
ContextItems = requestItems;
}
private Func<IDictionary<object, object>> ContextItems { get; }
public bool IsAvailable => TryGetContextItems(out _);
private bool TryGetContextItems(out IDictionary<object, object> items)
{
items = ContextItems?.Invoke();
return items != null;
}
/// <inheritdoc />
public override object Get(string key, Func<object> factory)
{
//no place to cache so just return the callback result
if (!TryGetContextItems(out var items)) return factory();
key = GetCacheKey(key);
Lazy<object> result;
try
{
EnterWriteLock();
result = items[key] as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just
// do nothing here - means that if creation throws, a race condition could cause
// more than one thread to reach the return statement below and throw - accepted.
if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
{
result = SafeLazy.GetSafeLazy(factory);
items[key] = result;
}
}
finally
{
ExitWriteLock();
}
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
// exceptions (but try again and again) and silently eat them - however at
// some point we have to report them - so need to re-throw here
// this does not throw anymore
//return result.Value;
var value = result.Value; // will not throw (safe lazy)
if (value is SafeLazy.ExceptionHolder eh) eh.Exception.Throw(); // throw once!
return value;
}
public bool Set(string key, object value)
{
//no place to cache so just return the callback result
if (!TryGetContextItems(out var items)) return false;
key = GetCacheKey(key);
try
{
EnterWriteLock();
items[key] = SafeLazy.GetSafeLazy(() => value);
}
finally
{
ExitWriteLock();
}
return true;
}
public bool Remove(string key)
{
//no place to cache so just return the callback result
if (!TryGetContextItems(out var items)) return false;
key = GetCacheKey(key);
try
{
EnterWriteLock();
items.Remove(key);
}
finally
{
ExitWriteLock();
}
return true;
}
#region Entries
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
{
const string prefix = CacheItemPrefix + "-";
if (!TryGetContextItems(out var items)) return Enumerable.Empty<DictionaryEntry>();
return items.Cast<DictionaryEntry>()
.Where(x => x.Key is string s && s.StartsWith(prefix));
}
protected override void RemoveEntry(string key)
{
if (!TryGetContextItems(out var items)) return;
items.Remove(key);
}
protected override object GetEntry(string key)
{
return !TryGetContextItems(out var items) ? null : items[key];
}
#endregion
#region Lock
private const string ContextItemsLockKey = "Umbraco.Core.Cache.HttpRequestCache::LockEntered";
protected override void EnterReadLock() => EnterWriteLock();
protected override void EnterWriteLock()
{
if (!TryGetContextItems(out var items)) return;
// note: cannot keep 'entered' as a class variable here,
// since there is one per request - so storing it within
// ContextItems - which is locked, so this should be safe
var entered = false;
Monitor.Enter(items, ref entered);
items[ContextItemsLockKey] = entered;
}
protected override void ExitReadLock() => ExitWriteLock();
protected override void ExitWriteLock()
{
if (!TryGetContextItems(out var items)) return;
var entered = (bool?)items[ContextItemsLockKey] ?? false;
if (entered)
Monitor.Exit(items);
items.Remove(ContextItemsLockKey);
}
#endregion
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
if (!TryGetContextItems(out var items))
{
yield break;
}
foreach (var item in items)
{
yield return new KeyValuePair<string, object>(item.Key.ToString(), item.Value);
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

View File

@@ -25,6 +25,7 @@ namespace Umbraco.Core.Runtime
private IFactory _factory;
private readonly RuntimeState _state;
private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker;
private readonly IRequestCache _requestCache;
private readonly IGlobalSettings _globalSettings;
private readonly IConnectionStrings _connectionStrings;
@@ -39,7 +40,8 @@ namespace Umbraco.Core.Runtime
IBackOfficeInfo backOfficeInfo,
IDbProviderFactoryCreator dbProviderFactoryCreator,
IMainDom mainDom,
ITypeFinder typeFinder)
ITypeFinder typeFinder,
IRequestCache requestCache)
{
IOHelper = ioHelper;
Configs = configs;
@@ -50,6 +52,7 @@ namespace Umbraco.Core.Runtime
DbProviderFactoryCreator = dbProviderFactoryCreator;
_umbracoBootPermissionChecker = umbracoBootPermissionChecker;
_requestCache = requestCache;
Logger = logger;
MainDom = mainDom;
@@ -110,6 +113,7 @@ namespace Umbraco.Core.Runtime
{
if (register is null) throw new ArgumentNullException(nameof(register));
// create and register the essential services
// ie the bare minimum required to boot
@@ -129,12 +133,25 @@ namespace Umbraco.Core.Runtime
"Booted.",
"Boot failed."))
{
Logger.Info<CoreRuntime>("Booting Core");
Logger.Info<CoreRuntime>("Booting site '{HostingSiteName}', app '{HostingApplicationId}', path '{HostingPhysicalPath}', server '{MachineName}'.",
HostingEnvironment?.SiteName,
HostingEnvironment?.ApplicationId,
HostingEnvironment?.ApplicationPhysicalPath,
NetworkHelper.MachineName);
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
// application environment
ConfigureUnhandledException();
return _factory = Configure(register, timer);
_factory = Configure(register, timer);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
// fail to resolve - but we run Initialize within a factory scope - and then,
// here, we switch the factory to bind scopes to requests
_factory.EnablePerWebRequestScope();
return _factory;
}
}
@@ -151,7 +168,7 @@ namespace Umbraco.Core.Runtime
try
{
// run handlers
RuntimeOptions.DoRuntimeBoot(ProfilingLogger);
@@ -350,7 +367,7 @@ namespace Umbraco.Core.Runtime
return new AppCaches(
new DeepCloneAppCache(new ObjectCacheAppCache()),
NoAppCache.Instance,
_requestCache,
new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache())));
}

View File

@@ -1,90 +0,0 @@
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.Runtime
{
/// <summary>
/// Represents the Web Umbraco runtime.
/// </summary>
/// <remarks>On top of CoreRuntime, handles all of the web-related runtime aspects of Umbraco.</remarks>
public class WebRuntime : CoreRuntime
{
private readonly IRequestCache _requestCache;
/// <summary>
/// Initializes a new instance of the <see cref="WebRuntime"/> class.
/// </summary>
public WebRuntime(
Configs configs,
IUmbracoVersion umbracoVersion,
IIOHelper ioHelper,
ILogger logger,
IProfiler profiler,
IHostingEnvironment hostingEnvironment,
IBackOfficeInfo backOfficeInfo,
IDbProviderFactoryCreator dbProviderFactoryCreator,
IMainDom mainDom,
ITypeFinder typeFinder,
IRequestCache requestCache,
IUmbracoBootPermissionChecker umbracoBootPermissionChecker):
base(configs, umbracoVersion, ioHelper, logger, profiler ,umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder)
{
_requestCache = requestCache;
}
/// <inheritdoc/>
public override IFactory Configure(IRegister register)
{
var profilingLogger = new ProfilingLogger(Logger, Profiler);
var umbracoVersion = new UmbracoVersion();
using (var timer = profilingLogger.TraceDuration<CoreRuntime>(
$"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.",
"Booted.",
"Boot failed."))
{
Logger.Info<CoreRuntime>("Booting site '{HostingSiteName}', app '{HostingApplicationId}', path '{HostingPhysicalPath}', server '{MachineName}'.",
HostingEnvironment.SiteName,
HostingEnvironment.ApplicationId,
HostingEnvironment.ApplicationPhysicalPath,
NetworkHelper.MachineName);
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
var factory = base.Configure(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
// fail to resolve - but we run Initialize within a factory scope - and then,
// here, we switch the factory to bind scopes to requests
factory.EnablePerWebRequestScope();
return factory;
}
}
#region Getters
protected override AppCaches GetAppCaches() => new AppCaches(
// we need to have the dep clone runtime cache provider to ensure
// all entities are cached properly (cloned in and cloned out)
new DeepCloneAppCache(new ObjectCacheAppCache()),
// we need request based cache when running in web-based context
_requestCache,
new IsolatedCaches(type =>
// we need to have the dep clone runtime cache provider to ensure
// all entities are cached properly (cloned in and cloned out)
new DeepCloneAppCache(new ObjectCacheAppCache())));
#endregion
}
}

View File

@@ -4,8 +4,10 @@ using Moq;
using NUnit.Framework;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Smidge;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Runtime;
@@ -57,7 +59,7 @@ namespace Umbraco.Tests.Integration
var coreRuntime = new CoreRuntime(testHelper.GetConfigs(), testHelper.GetUmbracoVersion(),
testHelper.IOHelper, testHelper.Logger, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker,
testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator,
testHelper.MainDom, testHelper.GetTypeFinder());
testHelper.MainDom, testHelper.GetTypeFinder(), NoAppCache.Instance);
// boot it!
var factory = coreRuntime.Configure(umbracoContainer);
@@ -99,7 +101,7 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, out _);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, NoAppCache.Instance, null, out _);
});
var host = await hostBuilder.StartAsync();
@@ -138,7 +140,7 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, out _);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, NoAppCache.Instance, null, out _);
});
var host = await hostBuilder.StartAsync();

View File

@@ -108,7 +108,7 @@ namespace Umbraco.Tests.Integration.Testing
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, out _);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, NoAppCache.Instance, null, out _);
});
var host = await hostBuilder.StartAsync();

View File

@@ -16,10 +16,10 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using Umbraco.Core.Strings;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Runtime;
using Umbraco.Core.Services;
using Umbraco.Tests.PublishedContent;
using Umbraco.Tests.Testing;
@@ -47,10 +47,10 @@ namespace Umbraco.Tests.Routing
HostingEnvironment);
}
public class TestRuntime : WebRuntime
public class TestRuntime : CoreRuntime
{
public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo)
: base(configs, umbracoVersion, ioHelper, Mock.Of<ILogger>(), Mock.Of<IProfiler>(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), TestHelper.GetRequestCache(), new AspNetUmbracoBootPermissionChecker())
: base(configs, umbracoVersion, ioHelper, Mock.Of<ILogger>(), Mock.Of<IProfiler>(), new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), TestHelper.GetRequestCache())
{
}

View File

@@ -5,6 +5,7 @@ using Examine;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
@@ -116,7 +117,7 @@ namespace Umbraco.Tests.Runtimes
public class TestRuntime : CoreRuntime
{
public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo)
:base(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder())
:base(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance)
{
}

View File

@@ -76,7 +76,7 @@ namespace Umbraco.Tests.Runtimes
var runtimeState = new RuntimeState(logger, null, umbracoVersion, backOfficeInfo);
var configs = TestHelper.GetConfigs();
var variationContextAccessor = TestHelper.VariationContextAccessor;
// create the register and the composition
var register = TestHelper.GetRegister();
@@ -84,7 +84,7 @@ namespace Umbraco.Tests.Runtimes
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance);
// determine actual runtime level
runtimeState.DetermineRuntimeLevel(databaseFactory, logger);
@@ -278,7 +278,7 @@ namespace Umbraco.Tests.Runtimes
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance);
// get the components
// all of them?
@@ -322,8 +322,8 @@ namespace Umbraco.Tests.Runtimes
Assert.AreEqual(0, results.Count);
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Reflection;
@@ -71,7 +73,13 @@ namespace Umbraco.Web.Common.Extensions
var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer;
services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly(), out factory);
IHttpContextAccessor httpContextAccessor = new HttpContextAccessor();
services.AddSingleton<IHttpContextAccessor>(httpContextAccessor);
var requestCache = new GenericDictionaryRequestAppCache(() => httpContextAccessor.HttpContext.Items);
services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly(), requestCache, httpContextAccessor, out factory);
return services;
}
@@ -83,20 +91,28 @@ namespace Umbraco.Web.Common.Extensions
/// <param name="webHostEnvironment"></param>
/// <param name="umbContainer"></param>
/// <param name="entryAssembly"></param>
/// <param name="requestCache"></param>
/// <param name="factory"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IRegister umbContainer, Assembly entryAssembly, out IFactory factory)
public static IServiceCollection AddUmbracoCore(
this IServiceCollection services,
IWebHostEnvironment webHostEnvironment,
IRegister umbContainer,
Assembly entryAssembly,
IRequestCache requestCache,
IHttpContextAccessor httpContextAccessor,
out IFactory factory)
{
if (services is null) throw new ArgumentNullException(nameof(services));
var container = umbContainer;
if (container is null) throw new ArgumentNullException(nameof(container));
if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly));
// Special case! The generic host adds a few default services but we need to manually add this one here NOW because
// we resolve it before the host finishes configuring in the call to CreateCompositionRoot
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var serviceProvider = services.BuildServiceProvider();
var configs = serviceProvider.GetService<Configs>();
CreateCompositionRoot(services, webHostEnvironment, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
CreateCompositionRoot(services, configs, httpContextAccessor, webHostEnvironment, out var logger, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
var globalSettings = configs.Global();
var umbracoVersion = new UmbracoVersion(globalSettings);
@@ -109,7 +125,8 @@ namespace Umbraco.Web.Common.Extensions
profiler,
hostingEnvironment,
backOfficeInfo,
CreateTypeFinder(logger, profiler, webHostEnvironment, entryAssembly));
CreateTypeFinder(logger, profiler, webHostEnvironment, entryAssembly),
requestCache);
factory = coreRuntime.Configure(container);
@@ -126,9 +143,10 @@ namespace Umbraco.Web.Common.Extensions
return new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(entryAssembly), runtimeHash);
}
private static IRuntime GetCoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger,
private static IRuntime GetCoreRuntime(
Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger,
IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo,
ITypeFinder typeFinder)
ITypeFinder typeFinder, IRequestCache requestCache)
{
var connectionStringConfig = configs.ConnectionStrings()[Constants.System.UmbracoConnectionName];
var dbProviderFactoryCreator = new SqlServerDbProviderFactoryCreator(
@@ -145,22 +163,27 @@ namespace Umbraco.Web.Common.Extensions
var mainDom = new MainDom(logger, mainDomLock);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetCoreBootPermissionsChecker(),
hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder);
var coreRuntime = new CoreRuntime(
configs,
umbracoVersion,
ioHelper,
logger,
profiler,
new AspNetCoreBootPermissionsChecker(),
hostingEnvironment,
backOfficeInfo,
dbProviderFactoryCreator,
mainDom,
typeFinder,
requestCache);
return coreRuntime;
}
private static IServiceCollection CreateCompositionRoot(IServiceCollection services, IWebHostEnvironment webHostEnvironment,
out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment,
private static IServiceCollection CreateCompositionRoot(IServiceCollection services, Configs configs, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment webHostEnvironment,
out ILogger logger, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment,
out IBackOfficeInfo backOfficeInfo, out IProfiler profiler)
{
// TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured
var serviceProvider = services.BuildServiceProvider();
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
configs = serviceProvider.GetService<Configs>();
if (configs == null)
throw new InvalidOperationException($"Could not resolve type {typeof(Configs)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}");
@@ -216,4 +239,5 @@ namespace Umbraco.Web.Common.Extensions
}
}

View File

@@ -1,4 +1,7 @@
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -34,10 +37,12 @@ namespace Umbraco.Web
var mainDom = new MainDom(logger, mainDomLock);
var requestCache = new HttpRequestAppCache(() => HttpContext.Current?.Items);
var requestCache = new HttpRequestAppCache(() => HttpContext.Current != null ? HttpContext.Current.Items : null);
var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker();
return new WebRuntime(configs, umbracoVersion, ioHelper, logger, profiler, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom,
GetTypeFinder(hostingEnvironment, logger, profiler), requestCache, umbracoBootPermissionChecker);
return new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom,
GetTypeFinder(hostingEnvironment, logger, profiler), requestCache);
}
}
}