Как получить уже кэшированные данные внутри метода контроллера Webapi C # - PullRequest
0 голосов
/ 11 мая 2018

Я создал атрибут OutputCacheFilter, унаследовав ActionFilterAttribute, чтобы получить функции кэширования для метода контроллера.

Это мой OutputCacheFilter класс

public class OutputCacheFilter : ActionFilterAttribute
    {
        // cache length in seconds
        private int _timespan;
        // true to enable cache
        private bool _cacheEnabled = false;
        // true if the cache depends on the caller user
        private readonly bool _dependsOnIdentity;
        // cache repository
        private static readonly ObjectCache WebApiCache = MemoryCache.Default;
        //private readonly SecurityHelper _securityHelper;
        private readonly bool _invalidateCache;

    public OutputCacheFilter()
        : this(true)
    {
    }

    public OutputCacheFilter(bool dependsOnIdentity)
        : this(dependsOnIdentity, false)
    {
    }

    public OutputCacheFilter(bool dependsOnIdentity, bool invalidateCache)
    {
        //_securityHelper = new SecurityHelper();
        _dependsOnIdentity = dependsOnIdentity;
        _invalidateCache = invalidateCache;

        ReadConfig();
    }

    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        if (_cacheEnabled)
        {
            if (filterContext != null)
            {
                if (IsCacheable(filterContext))
                {
                    string _cachekey = string.Join(":", new string[]
                    {
                        filterContext.Request.RequestUri.OriginalString,
                        filterContext.Request.Headers.Accept.FirstOrDefault().ToString(),
                    });

                    //if (_dependsOnIdentity)
                    //    _cachekey = _cachekey.Insert(0, _securityHelper.GetUser());

                    if (WebApiCache.Contains(_cachekey))
                    {
                        //TraceManager.TraceInfo(String.Format
                        //("Cache contains key: {0}", _cachekey));

                        var val = (string)WebApiCache.Get(_cachekey);
                        if (val != null)
                        {
                            filterContext.Response = filterContext.Request.CreateResponse();
                            filterContext.Response.Content = new StringContent(val);
                            var contenttype = (MediaTypeHeaderValue)WebApiCache.Get(_cachekey + ":response-ct");
                            if (contenttype == null)
                                contenttype = new MediaTypeHeaderValue(_cachekey.Split(':')[1]);
                            filterContext.Response.Content.Headers.ContentType = contenttype;
                            return;
                        }
                    }
                }
            }
            else
            {
                throw new ArgumentNullException("actionContext");
            }
        }
    }

    public override void OnActionExecuted(HttpActionExecutedContext filterContext)
    {
        try
        {
            if (_cacheEnabled)
            {
                if (WebApiCache != null)
                {
                    string _cachekey = string.Join(":", new string[]
                    {
                        filterContext.Request.RequestUri.OriginalString,
                        filterContext.Request.Headers.Accept.FirstOrDefault().ToString(),
                    });

                    //if (_dependsOnIdentity)
                    //    _cachekey = _cachekey.Insert(0, _securityHelper.GetUser());

                    if (filterContext.Response != null && filterContext.Response.Content != null)
                    {
                        string body = filterContext.Response.Content.ReadAsStringAsync().Result;

                        if (WebApiCache.Contains(_cachekey))
                        {
                            WebApiCache.Set(_cachekey, body, DateTime.Now.AddSeconds(_timespan));
                            WebApiCache.Set(_cachekey + ":response-ct",
                            filterContext.Response.Content.Headers.ContentType, DateTime.Now.AddSeconds(_timespan));
                        }
                        else
                        {
                            WebApiCache.Add(_cachekey, body, DateTime.Now.AddSeconds(_timespan));
                            WebApiCache.Add(_cachekey + ":response-ct",
                            filterContext.Response.Content.Headers.ContentType, DateTime.Now.AddSeconds(_timespan));
                        }
                    }
                }
            }

            if (_invalidateCache)
            {
                CleanCache();
            }
        }
        catch (Exception ex)
        {
            //TraceManager.TraceError(ex);
        }
    }

    private static void CleanCache()
    {
        if (WebApiCache != null)
        {
            List<string> keyList = WebApiCache.Select(w => w.Key).ToList();
            foreach (string key in keyList)
            {
                WebApiCache.Remove(key);
            }
        }
    }

    private void ReadConfig()
    {
        if (!Boolean.TryParse(WebConfigurationManager.AppSettings["CacheEnabled"], out _cacheEnabled))
            _cacheEnabled = false;

        if (!Int32.TryParse(WebConfigurationManager.AppSettings["CacheTimespan"], out _timespan))
            _timespan = 1800;
    }

    private bool IsCacheable(HttpActionContext ac)
    {
        if (_timespan > 0)
        {
            if (ac.Request.Method == HttpMethod.Get)
                return true;
        }
        else
        {
            throw new InvalidOperationException("Wrong Arguments");
        }
        return false;
    }
}

Это Мой контроллер

public class MessageController : ApiController
{
    [OutputCacheFilter()]
    public IHttpActionResult GetMessages()
    {
        MesssageManager msgManager = null;
        try
        {
            msgManager = new MesssageManager();
            List<Message> messages = msgManager.GetMessages();
            return Ok(messages);
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            msgManager = null;
        }
    }


    public IHttpActionResult GetMessage(string messageCode)
    {
        Message msg = null;
        MesssageManager msgManager = null;
        try
        {
            if(string.IsNullOrEmpty(messageCode))
            {
                throw new Exception("Plase pass the messageCode in order to get the message.");
            }
            msgManager = new MesssageManager();
            List<Message> messages = msgManager.GetMessages();
            msg = messages.FirstOrDefault(o => o.Code.Equals(messageCode, StringComparison.InvariantCultureIgnoreCase));
            return Ok(msg);
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            msgManager = null;
        }
    }

}

Модель DTO

public class Message
{
    public int ID { get; set; }
    public string Code { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
    public char IsActive { get; set; }
}

В моем коллайдере есть два метода

  1. GetMessages - этот метод извлекает все сообщения из базы данных и сохраняет их в cache, поэтому для его выполнения используется атрибут OutputCacheFilter.

  2. GetMessage - этот метод используетсячтобы получить одно сообщение по messageCode, в данный момент вызывается метод базы данных, чтобы получить весь код, а затем в результате поиск сообщения по messageCode.Здесь я хочу получить сообщение из cache само по себе, вызвав тот же метод контроллера «GetMessages ()», поэтому, если кэш доступен, то получить результат из кэша еще из базы данных, как это делает GetMessages ().

Для этого я вызвал GetMessages() метод контроллера в моем GetMessage(), но он всегда извлекает сообщение из базы данных, он не учитывает кэшированное сообщение.

Пожалуйста, помогите мне реализоватьправильный подход для этого сценария.

...