Fixing that Output Cache storage providers could fail with an ObjectDisposedException due to a deferred delegate execution causing the usage of dependencies from a disposed lifetime scope.

This commit is contained in:
Lombiq
2015-05-30 01:37:31 +02:00
parent 3d25ca42c9
commit ee0bd03c04

View File

@@ -213,6 +213,12 @@ namespace Orchard.OutputCache.Filters {
response.Filter = captureStream; response.Filter = captureStream;
captureStream.Captured += (output) => { captureStream.Captured += (output) => {
try { try {
// Since this is a callback any call to injected dependencies can result in an Autofac exception: "Instances
// cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed."
// To prevent access to the original lifetime scope a new work context scope should be created here and dependencies
// should be resolved from it.
using (var scope = _workContextAccessor.CreateWorkContextScope()) {
var cacheItem = new CacheItem() { var cacheItem = new CacheItem() {
CachedOnUtc = _now, CachedOnUtc = _now,
Duration = cacheDuration, Duration = cacheDuration,
@@ -223,20 +229,23 @@ namespace Orchard.OutputCache.Filters {
CacheKey = _cacheKey, CacheKey = _cacheKey,
InvariantCacheKey = _invariantCacheKey, InvariantCacheKey = _invariantCacheKey,
Url = filterContext.HttpContext.Request.Url.AbsolutePath, Url = filterContext.HttpContext.Request.Url.AbsolutePath,
Tenant = _shellSettings.Name, Tenant = scope.Resolve<ShellSettings>().Name,
StatusCode = response.StatusCode, StatusCode = response.StatusCode,
Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray() Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray()
}; };
// Write the rendered item to the cache. // Write the rendered item to the cache.
_cacheStorageProvider.Remove(_cacheKey); var cacheStorageProvider = scope.Resolve<IOutputCacheStorageProvider>();
_cacheStorageProvider.Set(_cacheKey, cacheItem); cacheStorageProvider.Remove(_cacheKey);
cacheStorageProvider.Set(_cacheKey, cacheItem);
Logger.Debug("Item '{0}' was written to cache.", _cacheKey); Logger.Debug("Item '{0}' was written to cache.", _cacheKey);
// Also add the item tags to the tag cache. // Also add the item tags to the tag cache.
var tagCache = scope.Resolve<ITagCache>();
foreach (var tag in cacheItem.Tags) { foreach (var tag in cacheItem.Tags) {
_tagCache.Tag(tag, _cacheKey); tagCache.Tag(tag, _cacheKey);
}
} }
} }
finally { finally {