コード例 #1
0
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            Logger.Debug("Incoming request for URL '{0}'.", filterContext.RequestContext.HttpContext.Request.RawUrl);

            // This filter is not reentrant (multiple executions within the same request are
            // not supported) so child actions are ignored completely.
            if (filterContext.IsChildAction)
            {
                Logger.Debug("Action '{0}' ignored because it's a child action.", filterContext.ActionDescriptor.ActionName);
                return;
            }

            _now         = _clock.UtcNow;
            _workContext = _workContextAccessor.GetContext();

            var configurations = _cacheService.GetRouteConfigs();

            if (configurations.Any())
            {
                var route = filterContext.Controller.ControllerContext.RouteData.Route;
                var key   = _cacheService.GetRouteDescriptorKey(filterContext.HttpContext, route);
                _cacheRouteConfig = configurations.FirstOrDefault(c => c.RouteKey == key);
            }

            if (!RequestIsCacheable(filterContext))
            {
                return;
            }

            // Computing the cache key after we know that the request is cacheable means that we are only performing this calculation on requests that require it
            _cacheKey          = String.Intern(ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext)));
            _invariantCacheKey = ComputeCacheKey(filterContext, null);

            Logger.Debug("Cache key '{0}' was created.", _cacheKey);

            try {
                // Is there a cached item, and are we allowed to serve it?
                var allowServeFromCache = filterContext.RequestContext.HttpContext.Request.Headers["Cache-Control"] != "no-cache" || CacheSettings.IgnoreNoCache;
                var cacheItem           = GetCacheItem(_cacheKey);
                if (allowServeFromCache && cacheItem != null)
                {
                    Logger.Debug("Item '{0}' was found in cache.", _cacheKey);

                    // Is the cached item in its grace period?
                    if (cacheItem.IsInGracePeriod(_now))
                    {
                        // Render the content unless another request is already doing so.
                        if (Monitor.TryEnter(_cacheKey))
                        {
                            Logger.Debug("Item '{0}' is in grace period and not currently being rendered; rendering item...", _cacheKey);
                            BeginRenderItem(filterContext);
                            return;
                        }
                    }

                    // Cached item is not yet in its grace period, or is already being
                    // rendered by another request; serve it from cache.
                    Logger.Debug("Serving item '{0}' from cache.", _cacheKey);
                    ServeCachedItem(filterContext, cacheItem);
                    return;
                }

                // No cached item found, or client doesn't want it; acquire the cache key
                // lock to render the item.
                Logger.Debug("Item '{0}' was not found in cache or client refuses it. Acquiring cache key lock...", _cacheKey);
                if (Monitor.TryEnter(_cacheKey))
                {
                    Logger.Debug("Cache key lock for item '{0}' was acquired.", _cacheKey);

                    // Item might now have been rendered and cached by another request; if so serve it from cache.
                    if (allowServeFromCache)
                    {
                        cacheItem = GetCacheItem(_cacheKey);
                        if (cacheItem != null)
                        {
                            Logger.Debug("Item '{0}' was now found; releasing cache key lock and serving from cache.", _cacheKey);
                            Monitor.Exit(_cacheKey);
                            ServeCachedItem(filterContext, cacheItem);
                            return;
                        }
                    }
                }

                // Either we acquired the cache key lock and the item was still not in cache, or
                // the lock acquisition timed out. In either case render the item.
                Logger.Debug("Rendering item '{0}'...", _cacheKey);
                BeginRenderItem(filterContext);
            }
            catch {
                // Remember to release the cache key lock in the event of an exception!
                Logger.Debug("Exception occurred for item '{0}'; releasing any acquired lock.", _cacheKey);
                ReleaseCacheKeyLock();
                throw;
            }
        }
コード例 #2
0
        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var captureHandlerIsAttached = false;

            try {
                // This filter is not reentrant (multiple executions within the same request are
                // not supported) so child actions are ignored completely.
                if (filterContext.IsChildAction || !_isCachingRequest)
                {
                    return;
                }

                Logger.Debug("Item '{0}' was rendered.", _cacheKey);

                // Obtain individual route configuration, if any.
                CacheRouteConfig configuration = null;
                var configurations             = _cacheService.GetRouteConfigs();
                if (configurations.Any())
                {
                    var route = filterContext.Controller.ControllerContext.RouteData.Route;
                    var key   = _cacheService.GetRouteDescriptorKey(filterContext.HttpContext, route);
                    configuration = configurations.FirstOrDefault(c => c.RouteKey == key);
                }

                if (!ResponseIsCacheable(filterContext, configuration))
                {
                    filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                    filterContext.HttpContext.Response.Cache.SetNoStore();
                    filterContext.HttpContext.Response.Cache.SetMaxAge(new TimeSpan(0));
                    return;
                }

                // Determine duration and grace time.
                var cacheDuration  = configuration != null && configuration.Duration.HasValue ? configuration.Duration.Value : CacheSettings.DefaultCacheDuration;
                var cacheGraceTime = configuration != null && configuration.GraceTime.HasValue ? configuration.GraceTime.Value : CacheSettings.DefaultCacheGraceTime;

                // Include each content item ID as tags for the cache entry.
                var contentItemIds = _displayedContentItemHandler.GetDisplayed().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray();

                // Capture the response output using a custom filter stream.
                var response      = filterContext.HttpContext.Response;
                var captureStream = new CaptureStream(response.Filter);
                response.Filter         = captureStream;
                captureStream.Captured += (output) => {
                    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()
                            {
                                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()
                            };

                            // Write the rendered item to the cache.
                            var cacheStorageProvider = scope.Resolve <IOutputCacheStorageProvider>();
                            cacheStorageProvider.Remove(_cacheKey);
                            cacheStorageProvider.Set(_cacheKey, cacheItem);

                            Logger.Debug("Item '{0}' was written to cache.", _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 {
                        // Always release the cache key lock when the request ends.
                        ReleaseCacheKeyLock();
                    }
                };

                captureHandlerIsAttached = true;
            }
            finally {
                // If the response filter stream capture handler was attached then we'll trust
                // it to release the cache key lock at some point in the future when the stream
                // is flushed; otherwise we'll make sure we'll release it here.
                if (!captureHandlerIsAttached)
                {
                    ReleaseCacheKeyLock();
                }
            }
        }
コード例 #3
0
        protected virtual bool ResponseIsCacheable(ResultExecutedContext filterContext, CacheRouteConfig configuration)
        {
            if (filterContext.HttpContext.Request.Url == null)
            {
                return(false);
            }

            // Don't cache non-200 responses or results of a redirect.
            var response = filterContext.HttpContext.Response;

            if (response.StatusCode != (int)HttpStatusCode.OK || _transformRedirect)
            {
                return(false);
            }

            // Don't cache in individual route configuration says no.
            if (configuration != null && configuration.Duration == 0)
            {
                Logger.Debug("Response for item '{0}' will not be cached because route is configured to not be cached.", _cacheKey);
                return(false);
            }

            // Don't cache if request created notifications.
            var hasNotifications = !String.IsNullOrEmpty(Convert.ToString(filterContext.Controller.TempData["messages"]));

            if (hasNotifications)
            {
                Logger.Debug("Response for item '{0}' will not be cached because one or more notifications were created.", _cacheKey);
                return(false);
            }

            return(true);
        }
        public new void OnActionExecuting(ActionExecutingContext filterContext)
        {
            Logger.Debug("Incoming request for URL '{0}'.", filterContext.RequestContext.HttpContext.Request.RawUrl);

            // This filter is not reentrant (multiple executions within the same request are
            // not supported) so child actions are ignored completely.
            if (filterContext.IsChildAction)
            {
                Logger.Debug("Action '{0}' ignored because it's a child action.", filterContext.ActionDescriptor.ActionName);
                return;
            }

            _now         = _clock.UtcNow;
            _workContext = _workContextAccessor.GetContext();
            var configurations = _cacheService.GetRouteConfigs();

            if (configurations.Any())
            {
                var route = filterContext.Controller.ControllerContext.RouteData.Route;
                var key   = _cacheService.GetRouteDescriptorKey(filterContext.HttpContext, route);
                _cacheRouteConfig = configurations.FirstOrDefault(c => c.RouteKey == key);
            }

            #region Added
            var cachedUrl = _cacheAliasServices.GetByUrl(filterContext.RequestContext.HttpContext.Request.RawUrl);
            var keyToAdd  = "";
            if (cachedUrl != null)
            {
                if (_cacheRouteConfig == null)
                {
                    keyToAdd          = "CacheUrl=" + _tokenizer.Replace(cachedUrl.Url, new Dictionary <string, object>()) + ";";// { { "Content", part.ContentItem } };)
                    _cacheRouteConfig = cachedUrl;
                }
                else
                if (cachedUrl.Priority >= _cacheRouteConfig.Priority)
                {
                    keyToAdd          = "CacheUrl=" + _tokenizer.Replace(cachedUrl.Url, new Dictionary <string, object>()) + ";";
                    _cacheRouteConfig = cachedUrl;
                }
            }
            #endregion

            if (!RequestIsCacheable(filterContext))
            {
                return;
            }


            // filtro per archiviare il log delle chiamate autenticate loggate e non gestite dalla cache laser.
            if (_cacheAliasServices.Setting().ActiveLog&& _workContext.CurrentUser != null && CacheSettings.CacheAuthenticatedRequests && keyToAdd == "")
            {
                Logger.Information("Cache con chiave  => {0}", String.Intern(ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext))));
            }

            // filtro per PREVENIRE la cache delle chiamate autenticate loggate e non gestite dalla cache laser.
            if (_cacheAliasServices.Setting().PreventDefaultAuthenticatedCache&& _workContext.CurrentUser != null && CacheSettings.CacheAuthenticatedRequests && keyToAdd == "")
            {
                if (_cacheAliasServices.Setting().ActiveLog)
                {
                    Logger.Information("cache key vuota bloccata ");
                }
                return;
            }

            if (_cacheAliasServices.Setting().PreventDefaultNotContentItemAuthenticatedCache&& _workContext.CurrentUser != null && CacheSettings.CacheAuthenticatedRequests && keyToAdd == "" && (!((filterContext.ActionDescriptor.ActionName == "Display" && filterContext.ActionDescriptor.ControllerDescriptor.ControllerName == "Item") || filterContext.RequestContext.HttpContext.Request.RawUrl.ToLower().Contains("displayalias"))))
            {
                if (_cacheAliasServices.Setting().ActiveLog)
                {
                    Logger.Information("cache key vuota bloccata ");
                }
                return;
            }


            // Computing the cache key after we know that the request is cacheable means that we are only performing this calculation on requests that require it
            _cacheKey          = keyToAdd + String.Intern(ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext)));
            _invariantCacheKey = ComputeCacheKey(filterContext, null);

            Logger.Debug("Cache key '{0}' was created.", _cacheKey);

            try {
                // Is there a cached item, and are we allowed to serve it?
                var allowServeFromCache = filterContext.RequestContext.HttpContext.Request.Headers["Cache-Control"] != "no-cache" || CacheSettings.IgnoreNoCache;
                var cacheItem           = GetCacheItem(_cacheKey);
                if (allowServeFromCache && cacheItem != null)
                {
                    Logger.Debug("Item '{0}' was found in cache.", _cacheKey);

                    // Is the cached item in its grace period?
                    if (cacheItem.IsInGracePeriod(_now))
                    {
                        // Render the content unless another request is already doing so.
                        if (Monitor.TryEnter(_cacheKey))
                        {
                            Logger.Debug("Item '{0}' is in grace period and not currently being rendered; rendering item...", _cacheKey);
                            BeginRenderItem(filterContext);
                            return;
                        }
                    }

                    // Cached item is not yet in its grace period, or is already being
                    // rendered by another request; serve it from cache.
                    Logger.Debug("Serving item '{0}' from cache.", _cacheKey);
                    ServeCachedItem(filterContext, cacheItem);
                    return;
                }

                // No cached item found, or client doesn't want it; acquire the cache key
                // lock to render the item.
                Logger.Debug("Item '{0}' was not found in cache or client refuses it. Acquiring cache key lock...", _cacheKey);
                if (Monitor.TryEnter(_cacheKey))
                {
                    Logger.Debug("Cache key lock for item '{0}' was acquired.", _cacheKey);

                    // Item might now have been rendered and cached by another request; if so serve it from cache.
                    if (allowServeFromCache)
                    {
                        cacheItem = GetCacheItem(_cacheKey);
                        if (cacheItem != null)
                        {
                            Logger.Debug("Item '{0}' was now found; releasing cache key lock and serving from cache.", _cacheKey);
                            Monitor.Exit(_cacheKey);
                            ServeCachedItem(filterContext, cacheItem);
                            return;
                        }
                    }
                }

                // Either we acquired the cache key lock and the item was still not in cache, or
                // the lock acquisition timed out. In either case render the item.
                Logger.Debug("Rendering item '{0}'...", _cacheKey);
                BeginRenderItem(filterContext);
            }
            catch {
                // Remember to release the cache key lock in the event of an exception!
                Logger.Debug("Exception occurred for item '{0}'; releasing any acquired lock.", _cacheKey);
                ReleaseCacheKeyLock();
                throw;
            }
        }