似乎,一旦您将Response.Cache
的可缓存性设置为NoCache
,就无法再次更改它。以下是该问题的简单但完整的说明:
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);
}
我错过了什么吗?有没有办法做到这一点?
编辑:当然,如果我使用Reflection进行设置,它会起作用,但我担心当你设置为HttpCacheability.NoCache
时会发生其他事情,如果我去的话我会想念的在幕后..并且更愿意以官方支持的方式进行。
EDIT2: Private
似乎也发生了同样的事情;你能加强限制吗?
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);
}
答案 0 :(得分:1)
破解打开的Reflector,看看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
在静态构造函数中设置:
s_cacheabilityValues = new int[] { -1, 0, 2, 1, 4, 3, 100 };
Dirtied()
被调用,但它似乎只是设置了一些标志:
private void Dirtied()
{
this._isModified = true;
this._useCachedHeaders = false;
}
它确实看起来有更改值的规则,但看起来它们没有太大的影响。因此,使用反射改变可能是安全的。
fi.SetValue(Response.Cache, HttpCacheability.Private);
答案 1 :(得分:0)
事实上,似乎反思是唯一安全的方式。深入研究代码,您需要从Response的Cache属性中提取HttpCachePolicy类型的对象,如下所示:
public class HttpCachePolicyWrapper : HttpCachePolicyBase
{
private HttpCachePolicy _httpCachePolicy;
....
}
为此,只需使用反射来设置Response.Cache对象中正确对象的值,如下面的代码所示:
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);
这只是为zimdanen的答案添加了更多的完整步骤