<p>While writing a custom IHttpHandler I came across a behavior that I didn't expect concerning the HttpCachePolicy object.</p>

<p>My handler calculates and sets an entity-tag (using the SetETag method on the HttpCachePolicy associated with the current response object). If I set the cache-control to public using the SetCacheability method everything works like a charm and the server sends along the e-tag header. If I set it to private the e-tag header will be suppressed.</p>

<p>Maybe I just haven't looked hard enough but I haven't seen anything in the HTTP/1.1 spec that would justify this behavior. Why wouldn't you want to send E-Tag to browsers while still prohibiting proxies from storing the data?</p>

<pre><code>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; } }
}
</code></pre>

<p>Will return</p>

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

<p>But if we change it to public it'll return</p>

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

<p>I've run this on the ASP.NET development server and IIS6 so far with the same results. Also I'm unable to explicitly set the ETag using</p>

<pre><code>Response.AppendHeader("ETag", "static")
</code></pre>

<p><strong>Update</strong>: It's possible to append the ETag header manually when running in IIS7, I suspect this is caused by the tight integration between ASP.NET and the IIS7 pipeline.</p>

<p><strong>Clarification</strong>: It's a long question but the core question is this: <strong>why does ASP.NET do this, how can I get around it and should I?</strong></p>

<p><strong>Update</strong>: I'm going to accept <a href="https://stackoverflow.com/questions/32824/why-does-httpcacheabilityprivate-suppress-etags#34004">Tony's answer</a> since it's essentially correct (go Tony!). I found that if you want to emulate the HttpCacheability.Private fully you can set the cacheability to ServerAndPrivate but you also have call cache.<a href="http://msdn.microsoft.com/en-us/library/system.web.httpcachepolicy.setomitvarystar.aspx" rel="nofollow noreferrer">SetOmitVaryStar</a>(true) otherwise the cache will add the <strong>Vary: *</strong> header to the output and you don't want that. I'll edit that into the answer when I get edit permissions (or if you see this Tony perhaps you could edit your answer to include that call?)</p>

[{'answer_id': 33555, 'author': 'Duncan Smart', 'author_id': 1278, 'author_profile': 'https://Stackoverflow.com/users/1278', 'pm_score': 2, 'selected': False, 'text': "<p>Unfortunately if you look at <code>System.Web.HttpCachePolicy.UpdateCachedHeaders()</code> in .NET Reflector you see that there's an if statement specifically checking that the Cacheability is not Private before doing any ETag stuff. In any case, I've always found that <code>Last-Modified/If-Modified-Since</code> works well for our data and is a bit easier to monitor in Fiddler anyway.</p>\n"}, {'answer_id': 34004, 'author': 'TonyB', 'author_id': 3543, 'author_profile': 'https://Stackoverflow.com/users/3543', 'pm_score': 5, 'selected': True, 'text': "<p>I think you need to use HttpCacheability.ServerAndPrivate</p>\n\n<p>That should give you cache-control: private in the headers and let you set an ETag.</p>\n\n<p>The documentation on that needs to be a bit better.</p>\n\n<p><strong>Edit:</strong> Markus found that you also have call cache.SetOmitVaryStar(true) otherwise the cache will add the Vary: * header to the output and you don't want that.</p>\n"}, {'answer_id': 9935387, 'author': 'Moray McConnachie', 'author_id': 1302129, 'author_profile': 'https://Stackoverflow.com/users/1302129', 'pm_score': 1, 'selected': False, 'text': "<p>If like me you're unhappy with the workaround mentioned here of using Cacheability.ServerAndPrivate, and you really want to use Private instead - perhaps because you are customising pages individually for users and it makes no sense to cache on the server - then at least in .NET 3.5 you can set ETag through Response.Headers.Add and this works fine. </p>\n\n<p>N.B. if you do this you have to implement the comparison of the client headers yourself and the HTTP 304 response handling - not sure if .NET takes care of this for you under normal circumstances.</p>\n"}]
['https://Stackoverflow.com/questions/32824', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2114/']