在 ASP.NET MVC 中创建 ETag 过滤器
我想在 MVC 中创建一个 ETag 过滤器。 问题是我无法控制 Response.OutputStream,如果我能够做到这一点,我将简单地根据结果流计算 ETag。 我之前在 WCF 中做过这件事,但找不到任何简单的想法在 MVC 中做到这一点。
我希望能够写出这样的东西
[ETag]
public ActionResult MyAction()
{
var myModel = Factory.CreateModel();
return View(myModel);
}
有什么想法吗?
I would like to create an ETag filter in MVC.
The problem is that I can't control the Response.OutputStream, if I was able to do that I would simply calculate the ETag according to the result stream.
I did this thing before in WCF but couldn't find any simple idea to do that in MVC.
I want to be able to write something like that
[ETag]
public ActionResult MyAction()
{
var myModel = Factory.CreateModel();
return View(myModel);
}
Any idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是我能想到的最好的办法,我不太明白你无法控制 Response.OutputStream 的意思。
这应该有效,但事实并非如此。
显然,微软重写了 System.Web.HttpResponseStream.Read(Byte[] buffer, Int32 offset, Int32 count) ,以便它返回“不支持指定的方法。”,不知道为什么他们会这样做,因为它继承了 System.Web.HttpResponseStream.Read(Byte[] buffer, Int32 offset, Int32 count) 。 IO.Stream 基类...
它由以下资源混合而成,Response.OutputStream 是只写流,因此我们必须使用 Response.Filter 类来读取输出流,这有点奇怪,您必须使用过滤器上的过滤器,但它有效 =)
http://bytes.com/topic/c-sharp/answers/494721-md5-encryption-question-communication-java
http://www.codeproject.com/KB/files/Calculated_MD5_Checksum.aspx
http://blog.gregbrant .com/post/Adding-Custom-HTTP-Headers-to-an-ASPNET-MVC-Response.aspx
http://www.infoq.com/articles/etags
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
更新
经过一番努力,我终于能够让它发挥作用:
更多资源:
http://authors.aspalliance.com/aspxtreme/sys/Web/HttpResponseClassFilter.aspx
http://forums.asp.net/t/1380989.aspx/1
This is the best I could come up with, I didn't really understand what you meant by you can't control the Response.OutputStream.
This should work, but is doesn't.
Apparently Microsoft overrode System.Web.HttpResponseStream.Read(Byte[] buffer, Int32 offset, Int32 count) so that it returns "Specified method is not supported.", not sure why they would do that, since it inherits for the System.IO.Stream base class...
Which is mix up of the following resources, the Response.OutputStream is a write only stream, so we have to use a Response.Filter class to read the output stream, kind of quirky that you have to use a filter on a filter, but it works =)
http://bytes.com/topic/c-sharp/answers/494721-md5-encryption-question-communication-java
http://www.codeproject.com/KB/files/Calculating_MD5_Checksum.aspx
http://blog.gregbrant.com/post/Adding-Custom-HTTP-Headers-to-an-ASPNET-MVC-Response.aspx
http://www.infoq.com/articles/etags
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
Update
After much fighting I was finally able to get this to work:
More Resources:
http://authors.aspalliance.com/aspxtreme/sys/Web/HttpResponseClassFilter.aspx
http://forums.asp.net/t/1380989.aspx/1
非常感谢,这正是我一直在寻找的。
刚刚对 ETagFilter 进行了一个小修复,以便在内容未更改的情况下处理 304
Thanks a lot it is exactly what I was looking for.
Just made a small fix to the ETagFilter that will handle 304 in case that the content wasn't changed
有很多有希望的答案。但它们都不是完整的解决方案。而且这不是问题的一部分,也没有人提到它。但是 ETag 应该用于缓存验证。因此它应该与Cache-Control标头一起使用。因此,客户端甚至不必调用服务器,直到缓存过期(这可能是非常短的时间,具体取决于您的资源)。当缓存过期时,客户端会使用 ETag 发出请求并验证它。有关缓存的更多详细信息请参阅本文。
这是我使用 ETags 的 CacheControl 属性解决方案。它可以通过启用公共缓存等进行改进...但是我强烈建议您了解缓存并仔细修改它。如果您使用 HTTPS 并且端点受到保护,那么此设置应该没问题。
用法例如:使用 1 分钟客户端缓存:
There are quite a few promising answers. But none of them is complete solution. Also it was not part of the question and nobody mentioned it. But ETag should be used for Cache validation. Therefore it should be used with Cache-Control header. So clients don't even have to call the server until the cache expires (it can be very short period of time depends on your resource). When the cache expired then client makes a request with ETag and validate it. For more details about caching see this article.
Here is my CacheControl attribute solution with ETags. It can be improved e.g. with Public cache enabled, etc... However I strongly advise you to understand caching and modify it carefully. If you use HTTPS and the endpoints are secured then this setup should be fine.
Usage e.g: with 1 min client side caching:
这是我为解决这个问题而创建的代码 - 我从 gzip 继承,因为我也想对流进行 gzip(您始终可以使用常规流)
不同之处在于,我计算所有响应的 etag,而不仅仅是其中的一部分。
this is the code i created to solve this problem - i inherit from gzip because i want to gzip the stream as well ( you can always use a regular stream)
the difference is that i calculate the etag for all my response and not just chunk of it.