Reputation: 5626
It seems as if, once you set the cacheability on Response.Cache
to NoCache
, there's no way to change it again. Here is a simple but complete illustration of the issue:
protected void Page_Load(object sender, EventArgs e)
{
FieldInfo fi = typeof(HttpCachePolicy).GetField(
"_cacheability",
BindingFlags.NonPublic | BindingFlags.Instance);
// Default value = 6
HttpCacheability first = (HttpCacheability)fi.GetValue(Response.Cache);
// Can change it to Public
Response.Cache.SetCacheability(HttpCacheability.Public);
HttpCacheability second = (HttpCacheability)fi.GetValue(Response.Cache);
// Can change it to Private
Response.Cache.SetCacheability(HttpCacheability.Private);
HttpCacheability third = (HttpCacheability)fi.GetValue(Response.Cache);
// Can change it to NoCache
Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpCacheability fourth = (HttpCacheability)fi.GetValue(Response.Cache);
// Can't go back to Private! Stuck on NoCache
Response.Cache.SetCacheability(HttpCacheability.Private);
HttpCacheability fifth = (HttpCacheability)fi.GetValue(Response.Cache);
}
Am I missing something? Is there a way to do this?
EDIT: Of course, it works if I set it with Reflection, but I'm worried that there's something else happening when you set to HttpCacheability.NoCache
that I would miss if I went behind the scenes.. and would prefer to do it in an officially-supported way anyway.
EDIT2: Same thing seems to happen with Private
; can you only go more restrictive?
protected void Page_Load(object sender, EventArgs e)
{
FieldInfo fi = typeof(HttpCachePolicy).GetField(
"_cacheability",
BindingFlags.NonPublic | BindingFlags.Instance);
// Default value = 6
HttpCacheability first = (HttpCacheability)fi.GetValue(Response.Cache);
// Can change it to Private
Response.Cache.SetCacheability(HttpCacheability.Private);
HttpCacheability second = (HttpCacheability)fi.GetValue(Response.Cache);
// Can't change to Public! Stuck on Private
Response.Cache.SetCacheability(HttpCacheability.Public);
HttpCacheability third = (HttpCacheability)fi.GetValue(Response.Cache);
// Can change to NoCache - Can only go more restrictive?
Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpCacheability fourth = (HttpCacheability)fi.GetValue(Response.Cache);
}
Upvotes: 1
Views: 669
Reputation: 212
Indeed, it seems that reflection is the only safe way. Looking deeper in the code, you will need to extract the object of type HttpCachePolicy from the Cache property of the Response as you can see it below:
public class HttpCachePolicyWrapper : HttpCachePolicyBase
{
private HttpCachePolicy _httpCachePolicy;
....
}
To do so, just use reflection for setting the value of the correct object from the Response.Cache object like in the code below:
FieldInfo fi = typeof(HttpCachePolicy).GetField("_cacheability", BindingFlags.NonPublic | BindingFlags.Instance);
var objectToChange = (HttpCachePolicy)context.Response.Cache.GetType().GetField("_httpCachePolicy", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(context.Response.Cache);
fi.SetValue(objectToChange, HttpCacheability.Public);
This just adds more conrete steps to the zimdanen's answer
Upvotes: 0
Reputation: 5626
Cracked open Reflector and took a look inside HttpCachePolicy
:
public void SetCacheability(HttpCacheability cacheability)
{
if ((cacheability < HttpCacheability.NoCache) || (HttpCacheability.ServerAndPrivate < cacheability))
{
throw new ArgumentOutOfRangeException("cacheability");
}
if (s_cacheabilityValues[(int) cacheability] < s_cacheabilityValues[(int) this._cacheability])
{
this.Dirtied();
this._cacheability = cacheability;
}
}
s_cacheabilityValues
is set during the static constructor:
s_cacheabilityValues = new int[] { -1, 0, 2, 1, 4, 3, 100 };
Dirtied()
is called, but it just seems to set some flags:
private void Dirtied()
{
this._isModified = true;
this._useCachedHeaders = false;
}
It does look ilke there are rules for changing the values, but there doesn't look like they have much effect. As such, probably safe to just change using reflection.
fi.SetValue(Response.Cache, HttpCacheability.Private);
Upvotes: 1