Exemple #1
0
        public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
        {
            log4net.LogManager.GetLogger(this.GetType()).Info("start: OnActionExecutedAsync");

            if (CustomTimeSpanMethodClassType != null)
            {
                MambaDefinedShortTime mambaDefinedShortTimeObject = null;

                var requestLocalPath = actionExecutedContext.Request.RequestUri.LocalPath;

                mambaDefinedShortTimeObject = _mambaDefinedShortTimeObjects.FirstOrDefault(x => string.Compare(x.Key, requestLocalPath, true) == 0).Value;
                if (mambaDefinedShortTimeObject == null)
                {
                    if (string.IsNullOrWhiteSpace(CustomTimeSpanMethodName))
                    {
                        CustomTimeSpanMethodName = _defaultCustomTimeSpanMethodName;
                    }
                    var methodInfo = CustomTimeSpanMethodClassType.GetMethod(CustomTimeSpanMethodName);
                    if (methodInfo != null)
                    {
                        mambaDefinedShortTimeObject = new MambaDefinedShortTime(actionExecutedContext, methodInfo);
                        _mambaDefinedShortTimeObjects.Add(requestLocalPath, mambaDefinedShortTimeObject);
                    }
                }

                if (mambaDefinedShortTimeObject != null)
                {
                    var _cacheTimeQuery = this.GetType().GetField("CacheTimeQuery", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                    _cacheTimeQuery.SetValue(this, mambaDefinedShortTimeObject);
                }
            }

            //Copy&Paste the OnActionExecutedAsync, instead of calling base.OnActionExecutedAsync(), because of [*]
            #region Copy&Paste from CacheOutputAttribute, as is

            if (actionExecutedContext.ActionContext.Response == null || !actionExecutedContext.ActionContext.Response.IsSuccessStatusCode)
            {
                return;
            }

            if (!IsCachingAllowed(actionExecutedContext.ActionContext, AnonymousOnly))
            {
                return;
            }

            var cacheTime = CacheTimeQuery.Execute(DateTime.UtcNow);
            if (cacheTime.AbsoluteExpiration > DateTime.UtcNow || ExpirationMode == ExpirationMode.None)
            {
                var httpConfig = actionExecutedContext.Request.GetConfiguration();
                var config     = httpConfig.CacheOutputConfiguration();

                var cacheKeyGenerator = config.GetCacheKeyGenerator(actionExecutedContext.Request, typeof(CustomCacheKeyGenerator));
                if (cacheKeyGenerator is CustomCacheKeyGenerator)
                {
                    ((CustomCacheKeyGenerator)cacheKeyGenerator).CachePerUser = CachePerUser;
                    ((CustomCacheKeyGenerator)cacheKeyGenerator).ApiName      = ApiName;
                    ((CustomCacheKeyGenerator)cacheKeyGenerator).HeadersToInlcudeInCacheKey = HeadersToInlcudeInCacheKey;
                }

                var responseMediaType = actionExecutedContext.Request.Properties[CurrentRequestMediaType] as MediaTypeHeaderValue ?? GetExpectedMediaType(httpConfig, actionExecutedContext.ActionContext);
                var cachekey          = cacheKeyGenerator.MakeCacheKey(actionExecutedContext.ActionContext, responseMediaType, ExcludeQueryStringFromCacheKey);

                // Why do we check if it already exists in cache?
                //if (!string.IsNullOrWhiteSpace(cachekey) && !(_webApiCache.Contains(cachekey)))
                if (!string.IsNullOrWhiteSpace(cachekey))
                {
                    SetEtag(actionExecutedContext.Response, CreateEtag(actionExecutedContext, cachekey, cacheTime));

                    var responseContent = actionExecutedContext.Response.Content;

                    if (responseContent != null)
                    {
                        var    baseKey     = config.MakeBaseCachekey(actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName, actionExecutedContext.ActionContext.ActionDescriptor.ActionName);
                        var    contentType = responseContent.Headers.ContentType;
                        string etag        = actionExecutedContext.Response.Headers.ETag.Tag;

                        var content = await responseContent.ReadAsByteArrayAsync();//.ConfigureAwait(false);  [*]

                        responseContent.Headers.Remove("Content-Length");

                        if (_webApiCache is CustomCacheProvider)
                        {
                            ((CustomCacheProvider)_webApiCache).ExpirationTimeSpan = cacheTime.ClientTimeSpan;
                        }

                        _webApiCache.Add(baseKey, string.Empty, cacheTime.AbsoluteExpiration);
                        _webApiCache.Add(cachekey, content, cacheTime.AbsoluteExpiration, baseKey);


                        _webApiCache.Add(cachekey + Constants.ContentTypeKey,
                                         contentType,
                                         cacheTime.AbsoluteExpiration, baseKey);


                        _webApiCache.Add(cachekey + Constants.EtagKey,
                                         etag,
                                         cacheTime.AbsoluteExpiration, baseKey);
                    }
                }
            }

            ApplyCacheHeaders(actionExecutedContext.ActionContext.Response, cacheTime);
            #endregion

            log4net.LogManager.GetLogger(this.GetType()).Info("end: OnActionExecutedAsync");
        }// end OnActionExecutedAsync()
Exemple #2
0
        }// end OnActionExecutedAsync()

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            log4net.LogManager.GetLogger(this.GetType()).Debug("start: OnActionExecuting");

            if (actionContext == null)
            {
                throw new ArgumentNullException("actionContext");
            }

            if (!IsCachingAllowed(actionContext, AnonymousOnly))
            {
                return;
            }

            var timer = (Stopwatch)actionContext.Request.Properties["logtimer"];

            if (timer == null)
            {
                timer = new Stopwatch();
                timer.Start();
            }

            var config = actionContext.Request.GetConfiguration();

            EnsureCacheTimeQuery();
            EnsureCache(config, actionContext.Request);

            var cacheKeyGenerator = config.CacheOutputConfiguration().GetCacheKeyGenerator(actionContext.Request, typeof(CustomCacheKeyGenerator));

            if (cacheKeyGenerator is CustomCacheKeyGenerator)
            {
                ((CustomCacheKeyGenerator)cacheKeyGenerator).CachePerUser = CachePerUser;
                ((CustomCacheKeyGenerator)cacheKeyGenerator).ApiName      = ApiName;
                ((CustomCacheKeyGenerator)cacheKeyGenerator).HeadersToInlcudeInCacheKey = HeadersToInlcudeInCacheKey;
            }

            var responseMediaType = GetExpectedMediaType(config, actionContext);

            actionContext.Request.Properties[CurrentRequestMediaType] = responseMediaType;
            var cachekey = cacheKeyGenerator.MakeCacheKey(actionContext, responseMediaType, ExcludeQueryStringFromCacheKey);

            if (!_webApiCache.Contains(cachekey))
            {
                return;
            }

            if (actionContext.Request.Headers.IfNoneMatch != null)
            {
                var etag = _webApiCache.Get <string>(cachekey + Constants.EtagKey);
                if (etag != null)
                {
                    if (actionContext.Request.Headers.IfNoneMatch.Any(x => x.Tag == etag))
                    {
                        var time          = CacheTimeQuery.Execute(DateTime.UtcNow);
                        var quickResponse = actionContext.Request.CreateResponse(HttpStatusCode.NotModified);
                        ApplyCacheHeaders(quickResponse, time);
                        actionContext.Response = quickResponse;

                        // Log Api Access
                        if (LogEnabled && !(bool)actionContext.Request.Properties["requestIsLogged"])
                        {
                            timer.Stop();
                            APILogger?.LogExposedAPIAccess(_id, actionContext, timer.Elapsed, true);
                            actionContext.Request.Properties["requestIsLogged"] = true;
                        }

                        return;
                    }
                }
            }

            var val = _webApiCache.Get <byte[]>(cachekey);

            if (val == null)
            {
                return;
            }

            var contenttype = _webApiCache.Get <MediaTypeHeaderValue>(cachekey + Constants.ContentTypeKey) ?? responseMediaType;

            actionContext.Response         = actionContext.Request.CreateResponse();
            actionContext.Response.Content = new ByteArrayContent(val);

            actionContext.Response.Content.Headers.ContentType = contenttype;

            var responseEtag = _webApiCache.Get <string>(cachekey + Constants.EtagKey);

            if (responseEtag != null)
            {
                SetEtag(actionContext.Response, responseEtag);
            }

            var cacheTime = CacheTimeQuery.Execute(DateTime.UtcNow);

            ApplyCacheHeaders(actionContext.Response, cacheTime);
            log4net.LogManager.GetLogger(this.GetType()).Debug("end: OnActionExecuting");

            // Log Api Access
            if (LogEnabled && !(bool)actionContext.Request.Properties["requestIsLogged"])
            {
                timer.Stop();
                APILogger?.LogExposedAPIAccess(_id, actionContext, timer.Elapsed, true);
                actionContext.Request.Properties["requestIsLogged"] = true;
            }
        }