- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个 ASP.Net Web API Controller ,它只返回用户列表。
public sealed class UserController : ApiController
{
[EnableTag]
public HttpResponseMessage Get()
{
var userList= this.RetrieveUserList(); // This will return list of users
this.responseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent<List<UserViewModel>>(userList, new JsonMediaTypeFormatter())
};
return this.responseMessage;
}
}
和一个负责管理ETag和缓存的 Action 过滤器属性类EnableTag
:
public class EnableTag : System.Web.Http.Filters.ActionFilterAttribute
{
private static ConcurrentDictionary<string, EntityTagHeaderValue> etags = new ConcurrentDictionary<string, EntityTagHeaderValue>();
public override void OnActionExecuting(HttpActionContext context)
{
if (context != null)
{
var request = context.Request;
if (request.Method == HttpMethod.Get)
{
var key = GetKey(request);
ICollection<EntityTagHeaderValue> etagsFromClient = request.Headers.IfNoneMatch;
if (etagsFromClient.Count > 0)
{
EntityTagHeaderValue etag = null;
if (etags.TryGetValue(key, out etag) && etagsFromClient.Any(t => t.Tag == etag.Tag))
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotModified);
SetCacheControl(context.Response);
}
}
}
}
}
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var request = context.Request;
var key = GetKey(request);
EntityTagHeaderValue etag;
if (!etags.TryGetValue(key, out etag) || request.Method == HttpMethod.Put || request.Method == HttpMethod.Post)
{
etag = new EntityTagHeaderValue("\"" + Guid.NewGuid().ToString() + "\"");
etags.AddOrUpdate(key, etag, (k, val) => etag);
}
context.Response.Headers.ETag = etag;
SetCacheControl(context.Response);
}
private static void SetCacheControl(HttpResponseMessage response)
{
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(60),
MustRevalidate = true,
Private = true
};
}
private static string GetKey(HttpRequestMessage request)
{
return request.RequestUri.ToString();
}
}
以上代码创建了一个属性类来管理ETag。因此,在第一个请求中,它将创建一个新的 E-Tag,对于后续请求,它将检查是否存在任何 ETag。如果是这样,它将生成 Not Modified
HTTP 状态并返回给客户端。
我的问题是,如果我的用户列表发生变化,我想创建一个新的 ETag,例如。添加新用户,或删除现有用户。并将其附加到响应中。这可以通过 userList
变量进行跟踪。
目前,从客户端和服务器接收到的 ETag 在每个第二个请求中都是相同的,因此在这种情况下,它将始终生成 Not Modified
状态,而我想要的是实际上没有任何变化。
谁能指导我朝这个方向发展?
最佳答案
我的要求是缓存我的 web api JSON 响应......并且提供的所有解决方案都没有一个简单的“链接”到生成数据的位置 - 即在 Controller 中......
所以我的解决方案是创建一个包装器“CacheableJsonResult”,它生成一个响应,然后将 ETag 添加到 header 。这允许在生成 Controller 方法并想要返回内容时传入一个etag...
public class CacheableJsonResult<T> : JsonResult<T>
{
private readonly string _eTag;
private const int MaxAge = 10; //10 seconds between requests so it doesn't even check the eTag!
public CacheableJsonResult(T content, JsonSerializerSettings serializerSettings, Encoding encoding, HttpRequestMessage request, string eTag)
:base(content, serializerSettings, encoding, request)
{
_eTag = eTag;
}
public override Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
{
Task<HttpResponseMessage> response = base.ExecuteAsync(cancellationToken);
return response.ContinueWith<HttpResponseMessage>((prior) =>
{
HttpResponseMessage message = prior.Result;
message.Headers.ETag = new EntityTagHeaderValue(String.Format("\"{0}\"", _eTag));
message.Headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromSeconds(MaxAge)
};
return message;
}, cancellationToken);
}
}
然后,在您的 Controller 中 - 返回此对象:
[HttpGet]
[Route("results/{runId}")]
public async Task<IHttpActionResult> GetRunResults(int runId)
{
//Is the current cache key in our cache?
//Yes - return 304
//No - get data - and update CacheKeys
string tag = GetETag(Request);
string cacheTag = GetCacheTag("GetRunResults"); //you need to implement this map - or use Redis if multiple web servers
if (tag == cacheTag )
return new StatusCodeResult(HttpStatusCode.NotModified, Request);
//Build data, and update Cache...
string newTag = "123"; //however you define this - I have a DB auto-inc ID on my messages
//Call our new CacheableJsonResult - and assign the new cache tag
return new CacheableJsonResult<WebsiteRunResults>(results, GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings, System.Text.UTF8Encoding.Default, Request, newTag);
}
}
private static string GetETag(HttpRequestMessage request)
{
IEnumerable<string> values = null;
if (request.Headers.TryGetValues("If-None-Match", out values))
return new EntityTagHeaderValue(values.FirstOrDefault()).Tag;
return null;
}
您需要定义制作标签的粒度;我的数据是特定于用户的,因此我将 UserId 包含在 CacheKey (etag) 中
关于c# - 如何使用 Action 过滤器和 HttpResponseMessage 在 Web API 中使用 ETag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20145140/
更新的问题 我的应用程序如何利用 etags,引入流/分块编码是否会带来任何复杂性? 原始问题 使用 Transfer-Encoding: chunked 进行 HTTP 流传输时, Content-
有谁知道在托管在单个网络服务器上的网络应用程序上禁用 ETag 是否值得?目前我们不在我们的应用程序中使用 ETag。 如果值得禁用它们 - 为什么? 非常感谢。 最佳答案 我不知道这是否有帮助,但您
我需要能够在以下条件下将实体插入到 azure 存储表中: 如果不存在,则插入。 如果存在,但我指定ETag为*,则替换。 如果存在,但 ETag 有另一个值,则抛出 StorageException
javascript 是否可以读取 HTTP 响应的 ETAG 值? 在向服务器的 HTTP 请求中写出 ETAG 值是否有任何问题? 最佳答案 如果它是一个定期加载的页面,我认为 HTTP 请求/响
标准的 GNU etags 不支持目录的递归遍历,就像 exuberant ctags -R 所做的那样。如果我只能访问 GNU etags,我如何使用 bash shell magic 让 etag
我无法可靠地在用户浏览器上设置 Etag。当用户点击我的一个外部链接时,我想将文章 ID 设置到他们的 Etag 中(我也使用 cookie,但我想专门试验 Etag 以测试其可靠性)。 当同一个用户
我已经通过 .htaccess 为静态站点设置了浏览器缓存通过设置文件: # BROWER CACHING - 1 Day for images Header set Cache-Control "
我了解使用 etags 进行乐观并发控制(例如,在 RESTful 架构风格中),并且我读过 etags 对于同一资源的不同表示应该是不同的。这是为什么? 最终我们是否有兴趣知道资源是否已更改以便我们
我对 OkHttp 以及它如何选择进行缓存有一些疑问: OkHttp 是否支持弱 ETag(在 Tomcat 7 中默认使用)?我在某处读到 Chrome 会忽略任何支持 Last-Modified
我开发了一个 ASP.NET Core 中间件解决方案,它计算与我正在执行的 GET 请求匹配的 ETag 的值,并在响应中返回它。 相关代码摘录如下: RequestHeaders requestH
我最近了解了 ETag HTTP header 的概念。 ( this ) 但我仍然有一个问题,对于负责生成 ETag 的特定 HTTP 资源? 换句话说,就是实际应用、容器(Ex:Tomcat)、W
我想为我的内容构建强大的 etag,您可以在图片中查看它。 在新选项卡中打开图像以查看大图.. 最佳答案 您对文件内容使用强大的哈希算法,例如 md5 或 sha-1。 HTTP 规范中有关于弱 et
最近发现了与 HTTP ETag 有关的问题和我们的 CDN我试图在 Fiddler 中为知名站点捕获一些。然而,无论我使用何种浏览器/网站组合,我都没有看到任何经过。 这有什么原因吗?你能建议我可以
许多 REST API 提供了搜索资源的能力。 例如,可以使用以下 HTTP 请求获取类型 A 的资源: GET /A?prop1={value1}&prop2={value2} 我正在使用乐观锁定,
即使我发送“cache-control: must-revalidate”,谷歌浏览器在浏览器中使用前后按钮时也会使用本地缓存页面。 这是原始回复的一部分: HTTP/1.1 200 OK cache
Redbot报告我的网页标题无效: The ETag header's syntax isn't valid. 我的标题设置为: ETag: 4ae413bd 为什么无效? ETag 的语法是什么?
HTTP 协议(protocol)是否规定了 ETag 的最大长度? 最佳答案 No . 14.19 ETag The ETag response-header field provides the
我一直在读一本书,我对 ETag 章节有一个特别的疑问。作者说 ETag 可能会损害性能,您必须对它们进行微调或完全禁用它们。 我已经知道什么是 ETag 并了解其中的风险,但是正确使用 ETag 有
我在做什么 我从数据库中提取图像并将其与所有正确的 header 一起发送到浏览器 - 图像显示正常。我还发送了一个 ETag header ,使用图像内容的 SHA1 作为标签。 图片半定期调用,所
我在更新存储桶 S3 时尝试使用 etag,但出现此错误: Error: Error in function call on config.tf line 48, in resource "aw
我是一名优秀的程序员,十分优秀!