1. 程式人生 > >ASP.Net Web API 輸出快取 轉載 -- Output caching in ASP.NET Web API

ASP.Net Web API 輸出快取 轉載 -- Output caching in ASP.NET Web API

一.Nuget安裝相關dll

 Web API 2 : Install-Package Strathweb.CacheOutput.WebApi2
 Web API 1 : Install-Package Strathweb.CacheOutput

二.新建一個 ActionFilterAttribute ,並重寫相關方法

    public class WebApiOutputCacheAttribute : ActionFilterAttribute
    {
        // 快取時間 /秒
        private int _timespan;
        // 客戶端快取時間 /秒
        private int _clientTimeSpan;
        // 是否為匿名使用者快取
        private bool _anonymousOnly;
        // 快取索引鍵
        private string _cachekey;
        // 快取倉庫
        private static readonly ObjectCache WebApiCache = MemoryCache.Default;


        public WebApiOutputCacheAttribute(int timespan, int clientTimeSpan, bool anonymousOnly)
        {
          _timespan = timespan;
          _clientTimeSpan = clientTimeSpan;
          _anonymousOnly = anonymousOnly;
        }

 //是否快取
        private bool _isCacheable(HttpActionContext ac)
        {
             if (_timespan > 0 && _clientTimeSpan > 0)
             {
                if (_anonymousOnly)
                   if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
                         return false;
               if (ac.Request.Method == HttpMethod.Get) return true;
            }
           else
           {
                throw new InvalidOperationException("Wrong Arguments");
           }
            return false;
        }

        private CacheControlHeaderValue setClientCache()
        {
            var cachecontrol = new CacheControlHeaderValue();
            cachecontrol.MaxAge = TimeSpan.FromSeconds(_clientTimeSpan);
            cachecontrol.MustRevalidate = true;
            return cachecontrol;
        }
 

 //Action呼叫前執行的方法
        public override void OnActionExecuting(HttpActionContext ac)
        {
            if (ac != null)
            {
                if (_isCacheable(ac))
                {
                    _cachekey = string.Join(":", new string[] { ac.Request.RequestUri.AbsolutePath, ac.Request.Headers.Accept.FirstOrDefault().ToString() });
                    if (WebApiCache.Contains(_cachekey))
                    {
                        var val = (string)WebApiCache.Get(_cachekey);
                        if (val != null)
                        {
                            ac.Response = ac.Request.CreateResponse();
                            ac.Response.Content = new StringContent(val);
                            var contenttype = (MediaTypeHeaderValue)WebApiCache.Get(_cachekey + ":response-ct");
                            if (contenttype == null)
                                contenttype = new MediaTypeHeaderValue(_cachekey.Split(':')[1]);
                            ac.Response.Content.Headers.ContentType = contenttype;
                            ac.Response.Headers.CacheControl = setClientCache();
                            return;
                        }
                    }
                }
            }
            else
            {
                throw new ArgumentNullException("actionContext");
            }
        }

 
 //Action呼叫後執行方法
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (!(WebApiCache.Contains(_cachekey)))
            {
                var body = actionExecutedContext.Response.Content.ReadAsStringAsync().Result;
                WebApiCache.Add(_cachekey, body, DateTime.Now.AddSeconds(_timespan));
                WebApiCache.Add(_cachekey + ":response-ct", actionExecutedContext.Response.Content.Headers.ContentType, DateTime.Now.AddSeconds(_timespan));
            }
            if (_isCacheable(actionExecutedContext.ActionContext))
                actionExecutedContext.ActionContext.Response.Headers.CacheControl = setClientCache();
        }

    }

三. 控制器的需要新增快取的Get方法新增該過濾器

     [WebApiOutputCache(120,60,false)]
        public string GetShoppingCart()
        {
            return "Hello World";
        }
啟動,觀察打斷點,觀察效果。整個過程是:啟動時先初始化該快取過濾器,客戶端呼叫添加了該過濾器的Get方法後,進入OnActionExecuting方法,判斷是否有相關的快取存在,如果有則直接返回結果,如否,則呼叫控制器的Action,再呼叫OnActionExecuted方法新增相關的快取鍵值對並設定快取過期時間,返回結果。

一.Nuget安裝相關dll

 Web API 2 : Install-Package Strathweb.CacheOutput.WebApi2
 Web API 1 : Install-Package Strathweb.CacheOutput

二.新建一個 ActionFilterAttribute ,並重寫相關方法

    public class WebApiOutputCacheAttribute : ActionFilterAttribute
    {
        // 快取時間 /秒
        private int _timespan;
        // 客戶端快取時間 /秒
        private int _clientTimeSpan;
        // 是否為匿名使用者快取
        private bool _anonymousOnly;
        // 快取索引鍵
        private string _cachekey;
        // 快取倉庫
        private static readonly ObjectCache WebApiCache = MemoryCache.Default;


        public WebApiOutputCacheAttribute(int timespan, int clientTimeSpan, bool anonymousOnly)
        {
          _timespan = timespan;
          _clientTimeSpan = clientTimeSpan;
          _anonymousOnly = anonymousOnly;
        }

 //是否快取
        private bool _isCacheable(HttpActionContext ac)
        {
             if (_timespan > 0 && _clientTimeSpan > 0)
             {
                if (_anonymousOnly)
                   if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
                         return false;
               if (ac.Request.Method == HttpMethod.Get) return true;
            }
           else
           {
                throw new InvalidOperationException("Wrong Arguments");
           }
            return false;
        }

        private CacheControlHeaderValue setClientCache()
        {
            var cachecontrol = new CacheControlHeaderValue();
            cachecontrol.MaxAge = TimeSpan.FromSeconds(_clientTimeSpan);
            cachecontrol.MustRevalidate = true;
            return cachecontrol;
        }
 

 //Action呼叫前執行的方法
        public override void OnActionExecuting(HttpActionContext ac)
        {
            if (ac != null)
            {
                if (_isCacheable(ac))
                {
                    _cachekey = string.Join(":", new string[] { ac.Request.RequestUri.AbsolutePath, ac.Request.Headers.Accept.FirstOrDefault().ToString() });
                    if (WebApiCache.Contains(_cachekey))
                    {
                        var val = (string)WebApiCache.Get(_cachekey);
                        if (val != null)
                        {
                            ac.Response = ac.Request.CreateResponse();
                            ac.Response.Content = new StringContent(val);
                            var contenttype = (MediaTypeHeaderValue)WebApiCache.Get(_cachekey + ":response-ct");
                            if (contenttype == null)
                                contenttype = new MediaTypeHeaderValue(_cachekey.Split(':')[1]);
                            ac.Response.Content.Headers.ContentType = contenttype;
                            ac.Response.Headers.CacheControl = setClientCache();
                            return;
                        }
                    }
                }
            }
            else
            {
                throw new ArgumentNullException("actionContext");
            }
        }

 
 //Action呼叫後執行方法
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (!(WebApiCache.Contains(_cachekey)))
            {
                var body = actionExecutedContext.Response.Content.ReadAsStringAsync().Result;
                WebApiCache.Add(_cachekey, body, DateTime.Now.AddSeconds(_timespan));
                WebApiCache.Add(_cachekey + ":response-ct", actionExecutedContext.Response.Content.Headers.ContentType, DateTime.Now.AddSeconds(_timespan));
            }
            if (_isCacheable(actionExecutedContext.ActionContext))
                actionExecutedContext.ActionContext.Response.Headers.CacheControl = setClientCache();
        }

    }

三. 控制器的需要新增快取的Get方法新增該過濾器

     [WebApiOutputCache(120,60,false)]
        public string GetShoppingCart()
        {
            return "Hello World";
        }
啟動,觀察打斷點,觀察效果。整個過程是:啟動時先初始化該快取過濾器,客戶端呼叫添加了該過濾器的Get方法後,進入OnActionExecuting方法,判斷是否有相關的快取存在,如果有則直接返回結果,如否,則呼叫控制器的Action,再呼叫OnActionExecuted方法新增相關的快取鍵值對並設定快取過期時間,返回結果。