首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法在.net核心中使用任何IDistributedCache作为ResponseCache?

有没有办法在.net核心中使用任何IDistributedCache作为ResponseCache?
EN

Stack Overflow用户
提问于 2020-05-01 06:44:50
回答 1查看 808关注 0票数 3

我想缓存从API到DistributedSqlServerCache的响应。默认ResponseCaching仅使用内存缓存。有一个构造函数,它允许配置要使用的缓存,但它是内部的。

我写了一个过滤器。如果响应没有被缓存,并且http响应是OK的,并且ActionResult是一个ObjectActionResult,那么它将该值序列化为JSON并将其保存到SQL缓存中。如果响应被缓存,它将对其进行反序列化,并将结果设置为具有反序列化对象的OkObject结果。

它工作得很好,但它有一些笨拙的东西(比如,要使用属性,你必须用typeof()指定将被反/序列化的类型)。

有没有一种方法可以缓存对分布式sql缓存的响应,而不涉及我自己的主要有效的解决方案?

另一种选择是复制粘贴netcore ResponseCacheMiddleWare,并对其进行修改以使用不同的缓存。我甚至可以把它做成一个nuget包。

有没有其他的解决方案?

这是我放在一起的过滤器(为了显示的目的而简化)

代码语言:javascript
复制
namespace Api.Filters
{
    /// <summary>
    /// Caches the result of the action as data.
    /// The action result must implement <see cref="ObjectResult"/>, and is only cached if the HTTP status code is OK.
    /// </summary>
    public class ResponseCache :  IAsyncResourceFilter
    {
        public Type ActionType { get; set; }

        public ExpirationType ExpirationType;

        private readonly IDistributedCache cache;

        public ResponseCache(IDistributedCache cache)
        {
            this.cache = cache;
        }

        public async Task OnResourceExecutionAsync(ResourceExecutingContext executingContext, ResourceExecutionDelegate next)
        {
            var key = getKey(executingContext);
            var cachedValue = await cache.GetAsync(key);

            if (cachedValue != null && executingContext.HttpContext.Request.Query["r"] == "cache")
            {
                await cache.RemoveAsync(key);
                cachedValue = null;
            }

            if (cachedValue != null)
            {
                executingContext.Result = new OkObjectResult(await fromBytes(cachedValue));
                return;
            }

            var executedContext = await next();

            // Only cache a successful response.
            if (executedContext.HttpContext.Response.StatusCode == StatusCodes.Status200OK && executedContext.Result is ObjectResult result)
            {
                await cache.SetAsync(key, await toBytes(result.Value), getExpiration());
            }
        }

        private async Task<byte[]> toBytes(object value)
        {
            using var stream = new MemoryStream();

            await JsonSerializer.SerializeAsync(stream, value, ActionType);

            return stream.ToArray();
        }

        private async Task<object> fromBytes(byte[] bytes)
        {
            using var stream = new MemoryStream(bytes);
            using var reader = new BinaryReader(stream, Encoding.Default, true);

            return await JsonSerializer.DeserializeAsync(stream, ActionType);
        }
    }

    public class ResponseCacheAttribute : Attribute, IFilterFactory
    {
        public bool IsReusable => true;

        public ExpirationType ExpirationType;

        public Type ActionType { get; set; }

        public ResponseCacheAttribute(params string[] queryParameters)
        {
            this.queryParameters = queryParameters;
        }

        public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
        {
            var cache = serviceProvider.GetService(typeof(IDistributedCache)) as IDistributedCache;

            return new ResponseCache(cache)
            {
                ExpirationType = ExpirationType,
                ActionType = ActionType
            };
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2020-05-07 11:29:51

最后,我做了一个nuget package,来源是on github。有关制作新包的原因的更多上下文,请参阅this issue

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61534019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档