2008-08-28 36 views
24

Trong khi viết một IHttpHandler tùy chỉnh, tôi bắt gặp một hành vi mà tôi không mong đợi liên quan đến đối tượng HttpCachePolicy.Tại sao HttpCacheability.Private ngăn chặn ETags?

Trình xử lý của tôi tính toán và đặt thẻ thực thể (sử dụng phương pháp SetETag trên HttpCachePolicy được liên kết với đối tượng phản hồi hiện tại). Nếu tôi đặt kiểm soát bộ nhớ cache cho công chúng bằng cách sử dụng phương thức SetCacheability, mọi thứ hoạt động như một nét duyên dáng và máy chủ gửi cùng với tiêu đề e-tag. Nếu tôi đặt nó thành riêng tư thì tiêu đề e-tag sẽ bị chặn.

Có lẽ tôi chưa đủ cứng nhưng tôi chưa thấy bất kỳ điều gì trong thông số HTTP/1.1 có thể biện minh cho hành vi này. Tại sao bạn không muốn gửi E-Tag cho trình duyệt trong khi vẫn cấm proxy lưu trữ dữ liệu?

using System; 
using System.Web; 

public class Handler : IHttpHandler { 
    public void ProcessRequest (HttpContext ctx) { 
     ctx.Response.Cache.SetCacheability(HttpCacheability.Private); 
     ctx.Response.Cache.SetETag("\"static\""); 
     ctx.Response.ContentType = "text/plain"; 
     ctx.Response.Write("Hello World"); 
    } 

    public bool IsReusable { get { return true; } } 
} 

Sẽ trở lại

 
Cache-Control: private 
Content-Type: text/plain; charset=utf-8 
Content-Length: 11 

Nhưng nếu chúng ta thay đổi nó thành công nó sẽ trở

 
Cache-Control: public 
Content-Type: text/plain; charset=utf-8 
Content-Length: 11 
Etag: "static" 

Tôi đã chạy trên máy chủ phát triển ASP.NET và IIS6 cho đến nay với cùng kết quả. Ngoài ra tôi không thể thiết lập một cách rõ ràng ETag sử dụng

Response.AppendHeader("ETag", "static") 

Cập nhật: Có thể thêm tiêu đề ETag bằng tay khi chạy trong IIS7, tôi nghi ngờ điều này là do sự tích hợp chặt chẽ giữa ASP.NET và IIS7 đường ống.

Làm rõ: Đó là một câu hỏi dài nhưng câu hỏi cốt lõi là: tại sao ASP.NET thực hiện việc này, làm cách nào tôi có thể sử dụng và tôi nên làm như thế nào?

Cập nhật: Tôi sẽ chấp nhận Tony's answer vì đó là bản chất chính xác (đi Tony!). Tôi thấy rằng nếu bạn muốn mô phỏng đầy đủ HttpCacheability.Private, bạn có thể đặt khả năng lưu trữ thành ServerAndPrivate nhưng bạn cũng có bộ nhớ cache cuộc gọi. SetOmitVaryStar (true) nếu không bộ nhớ cache sẽ thêm tiêu đề Thay đổi: * vào đầu ra và bạn không muốn điều đó. Tôi sẽ chỉnh sửa câu trả lời đó khi tôi nhận được quyền chỉnh sửa (hoặc nếu bạn thấy Tony này có lẽ bạn có thể chỉnh sửa câu trả lời của mình để bao gồm cuộc gọi đó?)

Trả lời

17

Tôi nghĩ rằng bạn cần phải sử dụng HttpCacheability.ServerAndPrivate

Điều đó sẽ cung cấp cho bạn bộ nhớ cache-control: tin trong tiêu đề và cho phép bạn đặt một ETag.

Tài liệu về điều đó cần phải tốt hơn một chút.

Edit: Markus thấy rằng bạn cũng có gọi cache.SetOmitVaryStar (true) nếu không thì bộ nhớ cache sẽ thêm Vary: * tiêu đề để đầu ra và bạn không muốn điều đó.

+2

Tôi không biết nếu [câu trả lời này] (http://stackoverflow.com/a/2633452/1869660) đến một câu hỏi khác mô tả lý do tại sao @Markus thêm cuộc gọi vào 'SetOmitVaryStar()', nhưng của ASP.NET 4.0 nó có thể không cần thiết nữa. – Sphinxxx

3

Thật không may nếu bạn nhìn vào số System.Web.HttpCachePolicy.UpdateCachedHeaders() trong .NET Reflector. một tuyên bố nếu cụ thể kiểm tra xem Cacheability không phải là Private trước khi thực hiện bất kỳ công cụ ETag nào. Trong mọi trường hợp, tôi luôn thấy rằng Last-Modified/If-Modified-Since hoạt động tốt cho dữ liệu của chúng tôi và dễ dàng hơn trong việc theo dõi trong Fiddler.

0

Nếu như tôi không hài lòng với giải pháp được đề cập ở đây khi sử dụng Cacheability.ServerAndPrivate và bạn thực sự muốn sử dụng Riêng tư - có lẽ vì bạn đang tùy chỉnh riêng từng trang cho người dùng và không có ý nghĩa gì đối với bộ nhớ cache trên máy chủ - sau đó ít nhất là trong NET 3.5. Bạn có thể đặt ETag thông qua Response.Headers.Add và điều này hoạt động tốt.

N.B. nếu bạn làm điều này, bạn phải thực hiện so sánh các tiêu đề của khách hàng và xử lý phản hồi HTTP 304 - không chắc chắn nếu .NET xử lý điều này cho bạn trong các trường hợp bình thường.

+3

Bạn luôn có thể gọi 'HttpCachePolicy.SetNoServerCaching' để tắt bộ nhớ đệm đầu ra (ví dụ: bộ nhớ đệm của máy chủ). Điều này sẽ ghi đè phần "máy chủ" của 'HttpCacheability.ServerAndPrivate'. –

+0

@WilliamGross Điều này có lẽ là câu trả lời được chấp nhận! Cảm ơn bạn. – James

Các vấn đề liên quan