2012-08-23 3 views
2

사용자 정의 캐싱이 필요한 일부 컨트롤러 작업이 있습니다. 예를 들어 컨트롤러 동작 ActionResult Index(string name) {}이 있다고 가정 해 보겠습니다. URL에 "live = true"쿼리 문자열 매개 변수가없는 한이 작업의 HTML을 서버에 캐시하고 싶습니다. 해당 매개 변수가 있으면 서버 캐시에서 해당 작업 결과를 제거하고 정상적으로 응답을 제공하고 싶습니다.MVC3에서 출력 캐시 사용자 정의

일반적으로 캐싱을 수행하기 위해 OutputCache(Location=OutputCacheLocation.Server) 속성을 사용합니다. 이 속성을 어떻게 든 확장하고 live = true 매개 변수가 URL에 있으면 캐시를 지울 수 있습니까?

필요한 동작을 얻기 위해 OutputCache 특성을 사용자 지정할 수없는 경우이를 수행하는 데 사용할 수있는 대안이 있습니까?

[LiveOutputCache(Location = OutputCacheLocation.Server, Duration = 60 * 60, VaryByParam = "name")] 
public ActionResult Index(string name) 
{ 
    ViewData.Model = name + "-----" + DateTime.Now.Ticks.ToString(); 
    return View(); 
} 

문제는 다음과 같습니다

여기
public class LiveOutputCacheAttribute : OutputCacheAttribute 
{ 
    private const string _resetParam = "live"; 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var context = filterContext.HttpContext; 
     AddLiveToVaryByParam(); 
     if (context.Request[_resetParam] == "true") 
     { 
      var urlToRemove = GetUrlToRemove(filterContext); 
      context.Response.RemoveOutputCacheItem(urlToRemove); 
      return; 
     } 
     base.OnActionExecuting(filterContext); 
    } 

    private void AddLiveToVaryByParam() 
    { 
     // add live reset flag when vary by param is specified 
     if (VaryByParam != "*" && !VaryByParam.Contains("live")) 
      VaryByParam = string.Format("{0};{1}",VaryByParam, _resetParam).TrimStart(';'); 
    } 

    private static string GetUrlToRemove(ActionExecutingContext filterContext) 
    { 
     var routeValues = new RouteValueDictionary(filterContext.ActionParameters); 
     var urlHelper = new UrlHelper(filterContext.RequestContext); 
     string action = filterContext.ActionDescriptor.ActionName; 
     string controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; 
     return urlHelper.Action(action, controller, routeValues); 
    } 
} 

나는 내 행동에 이것을 사용하는 방법입니다 : 여기에 제임스의 의견을 바탕으로

UPDATE

내가 가진 그 코드입니다 live = true 매개 변수를 사용하면 여전히 캐시에서 원래 요청을 제거하지 못합니다. 내가 여기서 뭔가 잘못하고있는거야?

+0

Custom Output Caching in ASP.NET MVC은 어쩌면 당신은 캐시에서 추가로 들어있는 항목을 제거하려고 매개 변수는 live = true이고, live가없는 것은 아닙니다. 캐시에서 제거하기 전에 "urlToRemove"값이 올바른지 확인하십시오. –

+0

urlToRemove 속성을 살펴 보았지만 "라이브"매개 변수가 없습니다. 라이브 패러미터가없는 Action 매개 변수에서 URL을 작성하기 때문에 기대할 수있는 것은 무엇입니까. –

답변

0

OutputCacheAttribute를 사용자 지정하여 동작을 가져올 수는 없지만 사용자가 CustomCacheAttribute를 작성하여이를 수행 할 수는 있습니다. 이렇게하려면 OutputCacheAttribute의 소스를 가져올 수 있습니다 (MVC는 오픈 소스이므로 할 수 있습니다). 복사하고 함수 OnActionExecuting(ActionExecutingContext filterContext)을 다시 씁니다.

3

속성을 사용하여 실제 옵션이 true인지 확인 할 수 있습니다.

public class LiveOutputCacheAttribute : OutputCacheAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (VaryByParam == "true") 
     { 
      // clear cache 
      return; 
     } 

     base.OnActionExecuting(filterContext); 
    } 
} 

... 

[LiveOutputCache(Location=OutputCacheLocation.Server, VaryByParam="live")] 
public ActionResult Index(string name) 
{ 
    ... 
} 

그것의 청산 부분 How to programmatically clear outputcache for controller action method를 참조하십시오.

+0

캐시를 지우지 않습니다. "생방송"으로 캐시되지 않은 리턴 만. –

+0

@KirillBestemyanov 예 나는 OP가 'live'매개 변수가 true 인 경우에만 캐싱을 활성화하려고한다고 생각하는 질문을 잘못 읽었습니다. – James

+0

제임스 감사합니다. 이것은 내가 필요한 것에 매우 가깝지만 정확히 작동하지는 않습니다. 내 수정 된 질문을보십시오. 감사 –

0

체크 아웃

MVC http://bstavroulakis.com/blog/web/custom-output-caching-in-asp-net-mvc/ ASP.NET에서 사용자 정의 출력 캐시를 만드는 방법에 대한 내 블로그 게시물을 내가했다)

1

을 만난 능력을 가지고하지 않은 출력 캐시에서 다음 기대 필요한 경우 캐싱 객체를보고 필요한 모든 부분을 무효화하십시오.

2) 필요할 때 캐싱을 사용하지 않도록 설정할 수 있습니다.

3) 항목이 캐시 된 전후에 일부 논리가 있습니다.

4) 정적 사이트

5)뿐만 아니라 사이트의 다른 부분에서 캐시 구조를 사용의 나머지는 데, 사이트 및로드 부분 만 동적 일부 되세요.

내 행동 여기서

  • 찾기/추가/제거 내 자신의 CacheManager/... 캐시에 객체를 생성합니다.그 후
    public class CacheManager 
        { 
         #region ICacheManager Members 
    
         public static void Add(string key, object value, int expireSeconds) 
         { 
          if (expireSeconds == CacheManagerKey.CacheLifeSpanForever) 
           WebCache.Add(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); 
          else 
           WebCache.Add(key, value, null, DateTime.MaxValue, TimeSpan.FromSeconds(expireSeconds), CacheItemPriority.Normal, null); 
         } 
    
         public static bool Contains(string key) 
         { 
          return WebCache.Get(key) != null; 
         } 
    
         public static int Count() 
         { 
          return WebCache.Count; 
         } 
    
         public static void Insert(string key, object value) 
         { 
          WebCache.Insert(key, value); 
         } 
    
         public static T Get(string key) 
         { 
          return (T)WebCache.Get(key); 
         } 
    
         public static List GetCacheKeys() 
         { 
          List keys = new List(); 
          foreach (DictionaryEntry entry in HttpContext.Current.Cache) keys.Add(entry.Key.ToString()); 
          return keys; 
         } 
    
         public static void Remove(string key) 
         { 
          WebCache.Remove(key); 
         } 
    
         public static void RemoveAll() 
         { 
          List keys = GetCacheKeys(); 
          foreach (string key in keys) 
           WebCache.Remove(key); 
         } 
    
         public object this[string key] 
         { 
          get 
          { 
           return WebCache[key]; 
          } 
          set 
          { 
           WebCache[key] = value; 
          } 
         } 
    
         #endregion 
    
         public static System.Web.Caching.Cache WebCache 
         { 
          get 
          { 
           System.Web.Caching.Cache cache = null; 
           if (HttpContext.Current != null) 
            cache = HttpContext.Current.Cache; 
    
           if (cache == null) 
            cache = HttpRuntime.Cache; 
    
           return cache; 
          } 
         } 
        } 
    
    은 내가 "Donut Caching"

  • 마지막을 사용하는 일부 동적 가지고 내 자신의 속성

 
     [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] 
     public class WebCacheAttribute : ActionFilterAttribute 
     { 
      public int Duration { get; set; } 
      public string CacheKey { get; set; } 
      public Dictionary CacheParams { get; set; } 
      public Type CacheReturnType { get; set; } 
      public string ContentType { get; set; } 
      public HeaderContentTypeEnum ResponseHeaderContentType{get;set;} 
      public string CacheObj { get; set; } 
      private readonly ICacheHoleFiller _cacheHoleFiller; 

      public WebCacheAttribute(int duration, string cacheKey, string cacheParamsStr, HeaderContentTypeEnum response = HeaderContentTypeEnum.Html, Type type = null) 
      { 

      } 

      public override void OnActionExecuting(ActionExecutingContext filterContext) 
      { 

      } 

      public T GetCachedParam(Dictionary parameters, bool isAjaxRequest) 
      { 

      } 

      public string GetUniqueKey(bool isAjaxRequest) 
      { 

      } 

      public void OnException(ExceptionContext filterContext) 
      { 

      } 

      private HtmlTextWriter tw; 
      private StringWriter sw; 
      private StringBuilder sb; 
      private HttpWriter output; 

      public override void OnResultExecuting(ResultExecutingContext filterContext) 
      { 

      } 

      public override void OnResultExecuted(ResultExecutedContext filterContext) 
      { 

      } 
    } 
  • 을 만들어, 내가 할 수있는 cachehelper을 생성 내 projec 다른 메서드를 호출하십시오. 웹 캐쉬 속성도 사용합니다. 당신이 내 블로그를 방문 할 수있는이 모든에 대한 자세한 내용은

var articleStr = CacheHelper.InvokeCacheMethod(typeof(HtmlHelperExtensions), "RenderArticlesCallback", new object[] { (int)articleType });
[WebCacheAttribute(CacheManagerKey.CacheLifeSpanForever, CacheManagerKey.Page_Article_Key, "articleTypeID")] 
      public static string RenderArticlesCallback(int articleTypeID) 
      {
public static class CacheHelper 
    { 
     public delegate object SourceDataDelegate(object[] args); 

     public static T InvokeCacheMethod(Type type, string methodName, object[] args) 
     { 
      return (T)InvokeCacheMethod(type, methodName, null, args); 
     } 

     public static T InvokeCacheMethod(Type type, string methodName, object instance, object[] args) 
     { 
      var method = type.GetMethod(methodName); 
      var webCache = method.ReturnParameter.Member.GetCustomAttributes(typeof(WebCacheAttribute), true).FirstOrDefault(); 
      Dictionary cacheParameters = FixCacheParameters(method, args); 
      T cachedObj; 

      if (Config.CacheEnabled && webCache != null) 
      { 
       cachedObj = ((WebCacheAttribute)webCache).GetCachedParam(cacheParameters, false); 
       if (cachedObj != null) 
        return cachedObj; 
      } 
      T returnObj = (T)method.Invoke(instance, args); 
      SaveCachedData(webCache, returnObj); 
      return returnObj; 
     } 

     public static void SaveCachedData(object webCache, object returnObj) 
     { 
      if (Config.CacheEnabled && webCache != null) 
      { 
       var fullParamString = ((WebCacheAttribute)webCache).GetUniqueKey(false); 
       CacheManager.Add(fullParamString, returnObj, ((WebCacheAttribute)webCache).Duration); 
      } 
     } 

     public static Dictionary FixCacheParameters(MethodInfo method, object[] args) 
     { 
      Dictionary cacheParameters = new Dictionary(); 
      if (args != null) 
      { 
       var arguments = args.ToList(); 
       var count = 0; 
       var argsCount = args.Length; 
       var methodParameters = method.GetParameters().ToList(); 

       foreach (var argument in args) 
       { 
        var key = methodParameters[count].Name; 
        object value = null; 

        if (argsCount > count) 
         value = args[count]; 

        if (value != null && value.GetType() == typeof(string)) 
         value = (object)value.ToString(); 

        if (value != null) 
         cacheParameters.Add(key, value); 

        count++; 
       } 
      } 

      return cacheParameters; 
     } 
    }

후 =>