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