zoukankan      html  css  js  c++  java
  • 在asp.net web api中利用过滤器设置输出缓存

    介绍

     本文将介绍如何在asp.net web api中利用过滤器属性实现缓存。

    实现过程

    1,首先在web.config文件下appsettings下定义“CacheEnabled”和“CacheTimespan”两个属性,

    CacheEnabled属性决定是否启用缓存

    CacheTimespan决定缓存过期时间戳

    如下代码所示:

       

    复制代码
      <appSettings>
        <!--<add key="webpages:Version" value="2.0.0.0" />
        <add key="webpages:Enabled" value="false" />
        <add key="PreserveLoginUrl" value="true" />
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />-->
        <add key="CacheEnabled" value="true"/>
        <add key="CacheTimespan" value="12000"/>
      </appSettings>
    复制代码

    2,添加WebApiOutputCacheAttribute类并继承ActionFilterAttribute ,需要添加引用:

    using System.Net.Http;
    using System.Web.Configuration;
    using System.Net.Http.Headers;
    using System.Net.Http.Formatting;

    代码相当简单和直白,就是在get方法执行前判断缓存key存在不存在,如果存在读取value,并输出,在过滤器执行完后更新缓存,如果不存在刚直接调用api中get方法,输出结果。

    复制代码
        public class WebApiOutputCacheAttribute :System.Web.Http.Filters.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;
    
            /// <summary>
            /// Constructor
            /// </summary>
            public WebApiOutputCacheAttribute()
                : this(true)
            {
            }
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="dependsOnIdentity"></param>
            public WebApiOutputCacheAttribute(bool dependsOnIdentity)
                : this(dependsOnIdentity, false)
            {
            }
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="dependsOnIdentity"></param>
            /// <param name="invalidateCache">true to invalidate cache object</param>
            public WebApiOutputCacheAttribute(bool dependsOnIdentity, bool invalidateCache)
            {
                //_securityHelper = new SecurityHelper();
                _dependsOnIdentity = dependsOnIdentity;
                _invalidateCache = invalidateCache;
    
                ReadConfig();
            }
    
            /// <summary>
            /// Called by the ASP.NET MVC framework before the action method executes.
            /// </summary>
            /// <param name="filterContext">The filter context.</param>
            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");
                    }
                }
            }
    
            /// <summary>
            /// Called by the ASP.NET MVC framework after the action method executes.
            /// </summary>
            /// <param name="filterContext">The filter context.</param>
            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);
                }
            }
    
            /// <summary>
            /// Removes all items from the cache
            /// </summary>
            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; // seconds
            }
    
            private bool IsCacheable(HttpActionContext ac)
            {
                if (_timespan > 0)
                {
                    if (ac.Request.Method == HttpMethod.Get)
                        return true;
                }
                else
                {
                    throw new InvalidOperationException("Wrong Arguments");
                }
                return false;
            }
        }
    复制代码

    在api中:

            // GET api/values/5
            [WebApiOutputCacheAttribute(true)]
            public string Get(int id)
            {
                return DateTime.Now.ToString();
            }
     
  • 相关阅读:
    死锁
    信号量
    实现临界区互斥的基本方法
    进程同步的基本概念:临界资源、同步和互斥
    操作系统典型调度算法
    [ 转]Collections.unmodifiableList方法的使用与场景
    【转】Android Support v4、v7、v13的区别和应用场景
    [转]finished with non-zero exit value 2
    [转]Git远程操作详解
    [转] git fetch与pull
  • 原文地址:https://www.cnblogs.com/yelanggu/p/10178755.html
Copyright © 2011-2022 走看看