OutputCache和RenderAction缓存整个页面

时间:2009-03-03 15:58:33

标签: asp.net asp.net-mvc caching

我有一个包含<% Html.RenderAction<MyController>(c => c.SidebarStats()); %>的ViewPage。在操作SidebarStats的控制器操作上,我有一个OutputCache操作过滤器,只缓存页面的那一部分。但是,整个页面都被缓存,而不仅仅是那个动作。

我记得在某个地方看到这可能是ASP.NET MVC的一个错误,虽然我不确定。我目前正在使用ASP.NET MVC RC1,IIS7,Windows Server 2008和.NET 3.5 SP1。

3 个答案:

答案 0 :(得分:10)

我在博客solution to this problem here上写了一篇文章。它很简单,但只有在使用WebFormViewEngine时才有效。我们将仔细研究如何使其适用于所有视图引擎。

答案 1 :(得分:2)

根据微软的说法,这是一个已知的错误,没有已知的修复程序。建议的解决方法是创建自己的OutputCache操作过滤器。

答案 2 :(得分:0)

我现在正在使用his blog中制作的 Steve Sanderson ,这非常好:

public class ActionOutputCacheAttribute : ActionFilterAttribute
{
    // This hack is optional; I'll explain it later in the blog post
    private static readonly MethodInfo _switchWriterMethod = typeof (HttpResponse).GetMethod("SwitchWriter",
                                                                                             BindingFlags.Instance |
                                                                                             BindingFlags.NonPublic);

    private readonly int _cacheDuration;
    private string _cacheKey;
    private TextWriter _originalWriter;

    public ActionOutputCacheAttribute(int cacheDuration)
    {
        _cacheDuration = cacheDuration;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _cacheKey = ComputeCacheKey(filterContext);
        var cachedOutput = (string) filterContext.HttpContext.Cache[_cacheKey];
        if (cachedOutput != null)
            filterContext.Result = new ContentResult {Content = cachedOutput};
        else
            _originalWriter =
                (TextWriter)
                _switchWriterMethod.Invoke(HttpContext.Current.Response,
                                           new object[] {new HtmlTextWriter(new StringWriter())});
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if (_originalWriter != null) // Must complete the caching
        {
            var cacheWriter =
                (HtmlTextWriter)
                _switchWriterMethod.Invoke(HttpContext.Current.Response, new object[] {_originalWriter});
            string textWritten = (cacheWriter.InnerWriter).ToString();
            filterContext.HttpContext.Response.Write(textWritten);

            filterContext.HttpContext.Cache.Add(_cacheKey, textWritten, null,
                                                DateTime.Now.AddSeconds(_cacheDuration), Cache.NoSlidingExpiration,
                                                CacheItemPriority.Normal, null);
        }
    }

    private string ComputeCacheKey(ActionExecutingContext filterContext)
    {
        var keyBuilder = new StringBuilder();
        foreach (var pair in filterContext.RouteData.Values)
            keyBuilder.AppendFormat("rd{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode());
        foreach (var pair in filterContext.ActionParameters)
            keyBuilder.AppendFormat("ap{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode());
        return keyBuilder.ToString();
    }
}

请访问Steve Sanderson blog's article了解详情。