2009-03-03 8 views
7

<% Html.RenderAction<MyController>(c => c.SidebarStats()); %>이 포함 된 ViewPage가 있습니다. SidebarStats 액션에 대한 컨트롤러 동작에는 페이지의 해당 부분 만 캐시하는 OutputCache 동작 필터가 있습니다. 그러나 전체 페이지가 캐시되지 않고 그 작업뿐입니다.OutputCache 및 RenderAction 전체 페이지 캐시

잘 모르겠지만 ASP.NET MVC의 버그 일 수 있습니다. 저는 현재 ASP.NET MVC RC1, IIS7, Windows Server 2008 및 .NET 3.5 SP1을 사용하고 있습니다.

답변

10

블로그는 solution to this problem here입니다. 간단하지만 WebFormViewEngine을 사용하는 경우에만 작동합니다. 우리는 모든 뷰 엔진에 대해이 작업을 수행하는 데 필요한 것이 무엇인지 파악하는 데 열심히 노력할 것입니다.

+0

당신 필 남자, 나는 우아한 해결책이 있어야한다는 것을 알고있었습니다. 감사! –

+2

V2에서이 버그가 수정 되었습니까? – CVertex

+1

@CVertex no. Razor 뷰 엔진을 사용하여 V3에서 수정 될 예정입니까? – stacker

2

Microsoft에 따르면이 버그는 알려진 수정 프로그램이 적용되지 않은 알려진 버그입니다. 제안 된 해결 방법은 고유 한 OutputCache 작업 필터를 만드는 것입니다.

0

지금 스티브 샌더슨his blog에서 만든 아주 좋은 무엇을 사용하고 있습니다 :

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를 방문하십시오.

+0

이것은 나에게 좋게 보인다! 나는 내가 그것을 시험해 볼 것이다라고 생각한다! –