首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当请求数据发生变化时,ResponseCache在.NET Core2.1中强制重新加载

当请求数据发生变化时,ResponseCache在.NET Core2.1中强制重新加载
EN

Stack Overflow用户
提问于 2018-11-23 13:48:10
回答 1查看 1.1K关注 0票数 0

我使用以下属性[ResponseCache(Duration = 60)]来缓存特定的GET请求,这在我的后端.NET Core中被称为“很多”。

除了当数据库中的某些数据在60秒内发生更改时,缓存没有重新加载之外,一切正常。

是否有我必须设置的特定指令来重新加载/更新缓存?链接

来自我的控制器的代码片段示例:

代码语言:javascript
复制
[HttpGet]
[ResponseCache(Duration = 60)]
public ActionResult<SomeTyp[]> SendDtos()
{
    var dtos = _repository.QueryAll();

    return Ok(dtos);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-23 17:42:23

有一个使用"ETag“、”如果-无匹配“的headers的解决方案。这个想法是使用一个代码,它可以给我们一个问题的答案:“行动的反应改变了吗?”如果控制器完全拥有特定的数据生存期,则可以这样做。

创建ITagProvider:

代码语言:javascript
复制
public interface ITagProvider
{
    string GetETag(string tagKey);
    void InvalidateETag(string tagKey);
}

创建一个动作过滤器:

代码语言:javascript
复制
public class ETagActionFilter : IActionFilter
{
    private readonly ITagProvider _tagProvider;

    public ETagActionFilter(ITagProvider tagProvider)
    {
        _tagProvider = tagProvider ?? throw new ArgumentNullException(nameof(tagProvider));
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        if (context.Exception != null)
        {
            return;
        }
        var uri = GetActionName(context.ActionDescriptor);
        var currentEtag = _tagProvider.GetETag(uri);
        if (!string.IsNullOrEmpty(currentEtag))
        {
            context.HttpContext.Response.Headers.Add("ETag", currentEtag);
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var uri = GetActionName(context.ActionDescriptor);
        var requestedEtag = context.HttpContext.Request.Headers["If-None-Match"];
        var currentEtag = _tagProvider.GetETag(uri);
        if (requestedEtag.Contains(currentEtag))
        {
            context.HttpContext.Response.Headers.Add("ETag", currentEtag);
            context.Result = new StatusCodeResult(StatusCodes.Status304NotModified);
        }
    }

    private string GetActionName(ActionDescriptor actionDescriptor)
    {
        return $"{actionDescriptor.RouteValues["controller"]}.{actionDescriptor.RouteValues["action"]}";
    }
}

Startup类中初始化过滤器:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    // code above
    services.AddMvc(options =>
        {
            options.Filters.Add(typeof(ETagActionFilter));
        });
    services.AddScoped<ETagActionFilter>();
    services.AddSingleton<ITagProvider, TagProvider>();
    // code below
}

在控制器中的某个位置使用InvalidateETag方法(在修改数据的位置):

代码语言:javascript
复制
    [HttpPost]
    public async Task<ActionResult> Post([FromBody] SomeType data)
    {
        // TODO: Modify data
        // Invalidate tag
        var tag = $"{controllerName}.{methodName}"
        _tagProvider.InvalidateETag(tag);
        return NoContent();
    }

此解决方案可能需要更改客户端。如果使用的是fetch,则可以使用以下库:https://github.com/export-mike/f-etag

我没有指定ITagProvider接口的实现,您需要自己编写。关于ETag和缓存的文章:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-cachinghttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag

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

https://stackoverflow.com/questions/53447908

复制
相关文章

相似问题

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