【问题标题】:Can eTag be used for smart client caching in asp.net MVC as in Rails?eTag 可以像在 Rails 中一样用于 asp.net MVC 中的智能客户端缓存吗?
【发布时间】:2009-09-19 19:31:58
【问题描述】:
我在this screencast ¹ 中发现您可以在 Ruby in Rails 中使用better client caching ² 考虑 REST + 模型来填充 eTag。比渲染所有的 http 正文更聪明,只有在这一切之后,像往常一样计算 eTag。
这个属性可以让客户端在使用GET的时候缓存更加面向模型,所以我觉得这对性能很有好处。
我没有看到有人用 asp.net MVC 做这个。会不会像我在 Rails 中看到这个人那样简单?
【问题讨论】:
标签:
ruby-on-rails
asp.net-mvc
etag
【解决方案1】:
eTag 是一个 HTTP 概念,而不是与任何一种服务器端技术相关。我相信,与 IIS/MVC 相比,RoR 可能更容易表明使用 eTag 缓存特定文件。
对于 IIS/MVC,您有两种设置响应标头的选项(可以包括 eTag 设置):
- 在 IIS 内容过期设置对话框中。
- 设置 HTTP 处理程序或类似技术,以便您准确指定特定请求所需的响应标头。这是第 1 步的程序化变体。如果您通过网络流式传输数据库内容,则必须这样做,在这种情况下,没有真正的文件可言。
如果还有其他我没有列出的方法来实现这一点,我很想知道它们。
【解决方案2】:
使用 ActionFilterAttribute 通过过滤器更新响应
public class ETagAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Filter = new ETagFilter(filterContext.HttpContext.Response, filterContext.RequestContext.HttpContext.Request);
}
}
public class ETagFilter : MemoryStream
{
private HttpResponseBase _response = null;
private HttpRequestBase _request;
private Stream _filter = null;
public ETagFilter(HttpResponseBase response, HttpRequestBase request)
{
_response = response;
_request = request;
_filter = response.Filter;
}
private string GetToken(Stream stream)
{
byte[] checksum = new byte[0];
checksum = MD5.Create().ComputeHash(stream);
return Convert.ToBase64String(checksum, 0, checksum.Length);
}
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
var token = GetToken(new MemoryStream(data));
string clientToken = _request.Headers["If-None-Match"];
if (token != clientToken)
{
_response.Headers["ETag"] = token;
_filter.Write(data, 0, count);
}
else
{
_response.SuppressContent = true;
_response.StatusCode = 304;
_response.StatusDescription = "Not Modified";
_response.Headers["Content-Length"] = "0";
}
}
}
原文来自:
Create ETag filter in ASP.NET MVC