2009-03-03 8 views
7

Ich habe eine ViewPage, die <% Html.RenderAction<MyController>(c => c.SidebarStats()); %> enthält. Auf der Controller-Aktion für die Aktion SidebarStats habe ich einen OutputCache-Aktionsfilter, um nur diesen Teil der Seite zwischenzuspeichern. Die gesamte Seite wird jedoch zwischengespeichert und nicht nur diese Aktion.OutputCache und RenderAction Cache ganze Seite

Ich erinnere mich irgendwo zu sehen, dass dies ein Fehler mit ASP.NET MVC sein könnte, obwohl ich mir nicht sicher bin. Ich verwende derzeit ASP.NET MVC RC1, IIS7, Windows Server 2008 und .NET 3.5 SP1.

Antwort

10

Ich bloggte ein solution to this problem here. Es ist einfach, aber es funktioniert nur, wenn Sie die WebFormViewEngine verwenden. Wir werden uns intensiv damit befassen, herauszufinden, was nötig ist, um dies für alle View Engines zu schaffen.

+0

Sie der Mann Phil, ich wusste, dass es eine elegante Lösung geben musste. Vielen Dank! –

+2

Wird dieser Fehler in V2 behoben? – CVertex

+1

@Certex-Nr. Wird dies in V3 behoben, wenn man mit der Razor View Engine arbeitet? – stacker

2

Laut Microsoft ist dies ein bekannter Fehler mit keine bekannte Lösung. Die vorgeschlagenen Problemumgehungen sind das Erstellen eines eigenen OutputCache-Aktionsfilters.

0

Ich verwende jetzt was Steve Sanderson in his blog gemacht und es ist sehr schön:

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

Bitte besuchen Steve Sanderson blog's article für weitere Informationen.

+0

Das sieht gut aus für mich! Ich denke, ich werde es versuchen! –