1

似乎,一旦将可缓存性设置Response.CacheNoCache,就无法再次更改它。这是该问题的简单但完整的说明:

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);
}

我错过了什么吗?有没有办法做到这一点?

编辑:当然,如果我用反射设置它,它会起作用,但我担心当你设置它时会发生其他事情,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);
}
4

2 回答 2

1

打开反射器并查看内部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);
于 2012-09-13T21:20:42.277 回答
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的答案增加了更多具体步骤

于 2015-01-07T10:39:15.387 回答