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方法新增相關的快取鍵值對並設定快取過期時間,返回結果。