• AspNet Core2 浏览器缓存使用


    Core2中使用Microsoft.AspNetCore.Mvc下的ResponseCacheAttribute特性来控制Http Get请求的缓存

    原理是设置http请求 响应头的Cache-control来告诉浏览器如何进行客户端缓存

    1、在Startup的ConfigureServices方法里面设置一个CacheProfiles,Duration属性定义浏览器缓存的秒数,CacheProfiles一个通用的缓存配置项

     services.AddMvc(option =>
                {
                    /*客户端缓存*/
                    option.CacheProfiles.Add("default", new Microsoft.AspNetCore.Mvc.CacheProfile
                    {
                        Duration = 600 /*10分钟*/
                    });
                });

    2、在需要缓存的Action上面添加ResponseCacheAttribute特性,CacheProfileName 的值使用服务配置的名称,该Action将使用配置项进行缓存

    [ResponseCache(CacheProfileName = "default")]

    也可以在Action 上赋予 Duration 值,指定浏览器缓存的时间  

     查看ResponseCacheAttribute中的代码

        public unsafe IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
            {
                //IL_0000: Unknown result type (might be due to invalid IL)
                //IL_0008: Unknown result type (might be due to invalid IL)
                //IL_000e: Unknown result type (might be due to invalid IL)
                //IL_0025: Unknown result type (might be due to invalid IL)
                //IL_0032: Expected Ref, but got Unknown
                //IL_0046: Unknown result type (might be due to invalid IL)
                if (serviceProvider == (IServiceProvider)0)
                {
                    throw new ArgumentNullException("serviceProvider");
                }
                IOptions<MvcOptions> requiredService = serviceProvider.GetRequiredService<IOptions<MvcOptions>>();
                CacheProfile cacheProfile = null;
                if (this.CacheProfileName != null)
                {
                    ((IDictionary)(?)requiredService.Value.CacheProfiles).TryGetValue((!0)this.CacheProfileName, ref *(!1*)(&cacheProfile));
                    if (cacheProfile == null)
                    {
                        throw new InvalidOperationException(Resources.FormatCacheProfileNotFound(this.CacheProfileName));
                    }
                }
                this._duration = (this._duration ?? ((cacheProfile != null) ? cacheProfile.Duration : null));
                this._noStore = (this._noStore ?? ((cacheProfile != null) ? cacheProfile.NoStore : null));
                this._location = (this._location ?? ((cacheProfile != null) ? cacheProfile.Location : null));
                this.VaryByHeader = (this.VaryByHeader ?? ((cacheProfile != null) ? cacheProfile.VaryByHeader : null));
                this.VaryByQueryKeys = (this.VaryByQueryKeys ?? ((cacheProfile != null) ? cacheProfile.VaryByQueryKeys : null));
                return new ResponseCacheFilter(new CacheProfile
                {
                    Duration = this._duration,
                    Location = this._location,
                    NoStore = this._noStore,
                    VaryByHeader = this.VaryByHeader,
                    VaryByQueryKeys = this.VaryByQueryKeys
                });
            }

    可以得知Action上设置-----优先级高于--CacheProfiles里面的配置

    缓存最终通过ResponseCacheFilter过滤器来实现,ResponseCacheFilter 的代码:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Core;
    using Microsoft.AspNetCore.Mvc.Filters;
    using Microsoft.AspNetCore.ResponseCaching;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    
    namespace Microsoft.AspNetCore.Mvc.Internal
    {
        /// <summary>
        /// An <see cref="T:Microsoft.AspNetCore.Mvc.Filters.IActionFilter" /> which sets the appropriate headers related to response caching.
        /// </summary>
        public class ResponseCacheFilter : IResponseCacheFilter, IActionFilter, IFilterMetadata
        {
            private readonly CacheProfile _cacheProfile;
    
            private int? _cacheDuration;
    
            private ResponseCacheLocation? _cacheLocation;
    
            private bool? _cacheNoStore;
    
            private string _cacheVaryByHeader;
    
            private string[] _cacheVaryByQueryKeys;
    
            /// <summary>
            /// Gets or sets the duration in seconds for which the response is cached.
            /// This is a required parameter.
            /// This sets "max-age" in "Cache-control" header.
            /// </summary>
            public int Duration
            {
                get
                {
                    return (this._cacheDuration ?? this._cacheProfile.Duration) ?? 0;
                }
                set
                {
                    this._cacheDuration = value;
                }
            }
    
            /// <summary>
            /// Gets or sets the location where the data from a particular URL must be cached.
            /// </summary>
            public ResponseCacheLocation Location
            {
                get
                {
                    return (this._cacheLocation ?? this._cacheProfile.Location) ?? ResponseCacheLocation.Any;
                }
                set
                {
                    this._cacheLocation = value;
                }
            }
    
            /// <summary>
            /// Gets or sets the value which determines whether the data should be stored or not.
            /// When set to <see langword="true" />, it sets "Cache-control" header to "no-store".
            /// Ignores the "Location" parameter for values other than "None".
            /// Ignores the "duration" parameter.
            /// </summary>
            public bool NoStore
            {
                get
                {
                    return (this._cacheNoStore ?? this._cacheProfile.NoStore) ?? false;
                }
                set
                {
                    this._cacheNoStore = value;
                }
            }
    
            /// <summary>
            /// Gets or sets the value for the Vary response header.
            /// </summary>
            public string VaryByHeader
            {
                get
                {
                    return this._cacheVaryByHeader ?? this._cacheProfile.VaryByHeader;
                }
                set
                {
                    this._cacheVaryByHeader = value;
                }
            }
    
            /// <summary>
            /// Gets or sets the query keys to vary by.
            /// </summary>
            /// <remarks>
            /// <see cref="P:Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter.VaryByQueryKeys" /> requires the response cache middleware.
            /// </remarks>
            public string[] VaryByQueryKeys
            {
                get
                {
                    return this._cacheVaryByQueryKeys ?? this._cacheProfile.VaryByQueryKeys;
                }
                set
                {
                    this._cacheVaryByQueryKeys = value;
                }
            }
    
            /// <summary>
            /// Creates a new instance of <see cref="T:Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter" />
            /// </summary>
            /// <param name="cacheProfile">The profile which contains the settings for
            /// <see cref="T:Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter" />.</param>
            public ResponseCacheFilter(CacheProfile cacheProfile)
            {
                this._cacheProfile = cacheProfile;
            }
    
            /// <inheritdoc />
            public void OnActionExecuting(ActionExecutingContext context)
            {
                //IL_0008: Unknown result type (might be due to invalid IL)
                //IL_0051: Unknown result type (might be due to invalid IL)
                //IL_00d4: Unknown result type (might be due to invalid IL)
                //IL_0185: Unknown result type (might be due to invalid IL)
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                }
                if (!this.IsOverridden(context))
                {
                    if (!this.NoStore && !this._cacheProfile.Duration.get_HasValue() && !this._cacheDuration.get_HasValue())
                    {
                        throw new InvalidOperationException(Resources.FormatResponseCache_SpecifyDuration("NoStore", "Duration"));
                    }
                    IHeaderDictionary headers = context.HttpContext.Response.Headers;
                    ((IDictionary)(?)headers).Remove((!0)"Vary");
                    ((IDictionary)(?)headers).Remove((!0)"Cache-Control");
                    ((IDictionary)(?)headers).Remove((!0)"Pragma");
                    if (!string.IsNullOrEmpty(this.VaryByHeader))
                    {
                        headers["Vary"] = this.VaryByHeader;
                    }
                    if (this.VaryByQueryKeys != null)
                    {
                        IResponseCachingFeature responseCachingFeature = context.HttpContext.Features.Get<IResponseCachingFeature>();
                        if (responseCachingFeature == null)
                        {
                            throw new InvalidOperationException(Resources.FormatVaryByQueryKeys_Requires_ResponseCachingMiddleware("VaryByQueryKeys"));
                        }
                        responseCachingFeature.VaryByQueryKeys = this.VaryByQueryKeys;
                    }
                    if (this.NoStore)
                    {
                        headers["Cache-Control"] = "no-store";
                        if (this.Location == ResponseCacheLocation.None)
                        {
                            headers.AppendCommaSeparatedValues("Cache-Control", "no-cache");
                            headers["Pragma"] = "no-cache";
                        }
                    }
                    else
                    {
                        string text = null;
                        switch (this.Location)
                        {
                        case ResponseCacheLocation.Any:
                            text = "public";
                            break;
                        case ResponseCacheLocation.Client:
                            text = "private";
                            break;
                        case ResponseCacheLocation.None:
                            text = "no-cache";
                            headers["Pragma"] = "no-cache";
                            break;
                        }
                        text = string.Format((IFormatProvider)CultureInfo.get_InvariantCulture(), "{0}{1}max-age={2}", (object)text, (object)((text != null) ? "," : null), (object)this.Duration);
                        if (text != null)
                        {
                            headers["Cache-Control"] = text;
                        }
                    }
                }
            }
    
            /// <inheritdoc />
            public void OnActionExecuted(ActionExecutedContext context)
            {
            }
    
            internal bool IsOverridden(ActionExecutingContext context)
            {
                //IL_0008: Unknown result type (might be due to invalid IL)
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                }
                return Enumerable.Last<IResponseCacheFilter>(Enumerable.OfType<IResponseCacheFilter>((IEnumerable)context.Filters)) != this;
            }
        }
    }
  • 相关阅读:
    gdb remote 使用
    gdb调试的layout使用
    经典名言--教父
    GDB dump mem example和命令
    再谈音响的七个频段,个个是真理
    Ubuntu 16.04下GDB调试
    shell脚本中if的“-e,-d,-f”
    ubuntu下makeinfo安装,其实真正安装的是texinfo包
    【svn】svn的使用
    【linux】监控磁盘情况并自动删除备份文件
  • 原文地址:https://www.cnblogs.com/tangchun/p/8967395.html
Copyright © 2020-2023  润新知