【问题标题】:OutputCache varying by a complex object propertyOutputCache 因复杂对象属性而异
【发布时间】:2013-03-04 01:56:49
【问题描述】:

我有一个控制器动作,它接收一个复杂对象作为参数,我需要 OutputCache 随这个复杂对象的属性之一而变化。这可能吗?怎么样?

【问题讨论】:

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


    【解决方案1】:

    如果你有这样的模型

    public class person{
     public string Name {get;set;}
     public string location {get;set;}
    } 
    

    在(强类型)视图中,您有一个表单

     @model Person
    
     @Html.BeginForm(){
      @Html.TextBoxFor(x=>x.Name)
      @Html.TextBoxFor(x=>x.location)
     }
    

    然后您将表单提交给ActionResult savePerson,并带有不同的签名,例如

    public ActionResult savePerson(Person p){
     // p.Name
     // p.location
    
    }
    

    public ActionResult savePerson(string Name, string location){
    
    }
    

    因此我认为如果你像这样注释 ActionResult

    [OutputCache(Duration=3600, VaryByParam="Name")]
    public ActionResult savePerson(Person p)
    {
        //
        return View();
    }
    

    它会为你做,或者如果你有一个复杂的模型,比如

    public class person{
     public string Name {get;set;}
     public Location loc {get;set;}
    } 
    public class Location{
      public string address
    }
    

    试试

    [OutputCache(Duration=3600, VaryByParam="Person.Location.address")]
    public ActionResult savePerson(Person p)
    {
        //
        return View();
    }
    

    【讨论】:

      【解决方案2】:

      我有与上述相同的要求,但想出了一个稍微不同的方法

      班级

      /// <summary>
      /// This class is used to encapsulate search filters for monitor graphs
      /// </summary>
      public class DatacarMonitorSearchCriteriaModel
      {
          public int? SynergyCode { get; set; }
      
          [Required]
          [DataType(DataType.Date)]
          public DateTime StartDate { get; set; }
      
          [Required]
          [DataType(DataType.Date)]
          public DateTime EndDate { get; set; }
      
          /// <summary>
          /// Filter to apply 
          /// </summary>
          public IEnumerable<int> Countries { get; set; }
      
      
          public DatacarMonitorSearchCriteriaModel()
          {
              Countries = new List<int>();
          }
      
      
      
      }
      

      OutputCacheComplexAttribute

      /// <summary>
      /// <para>
      ///     An instance of this class mimic the behaviour of OutputCacheAttribute but for complex objects.
      /// </para>
      /// <para>
      ///     It allows to cache the output of any action that takes complex objects 
      /// </para>
      /// </summary>
      public class OutputCacheComplexAttribute : OutputCacheAttribute
      {
          private readonly Type[] _types;
      
          private string _cachedKey;
      
          /// <summary>
          /// Initializes a new instance of the <see cref="OutputCacheComplexAttribute"/> class.
          /// </summary>
          /// <param name="types">Types that this attribute will lookup for in QueryString/Form data and store values in cache.</param>
          /// <exception cref="System.ArgumentOutOfRangeException">type;type cannot be null</exception>
          public OutputCacheComplexAttribute(params Type[] types)
          {
              if (types == null)
              {
                  throw new ArgumentOutOfRangeException("type", "type cannot be null");
              }
              _types = types;
          }
      
          public override void OnActionExecuting(ActionExecutingContext filterContext)
          {
              StringBuilder sbCachedKey = new StringBuilder();
              if (filterContext.HttpContext.Request.Url != null)
              {
                  string path = filterContext.HttpContext.Request.Url.PathAndQuery;
                  IDictionary<string, object> parameters = filterContext.ActionParameters;
      
                  //we need to compute a cache key which will be used to store the action output for later retrieval
                  //The cache key scheme is 
                  //    {url}:{key 1}:{value};[{key 2}:{value 2}[; ... {key n}:{value n}]];  
                  // where : 
                  //  - url is the url of the action that will be executed
                  //  - key n is the name of the n-th parameter
                  //  - value n is the value of the n-th parameter as json string.
                  foreach (KeyValuePair<string, object> kv in parameters)
                  {
                      var kv1 = kv;
                      if (kv.Value != null && _types.AtLeastOnce(t => t.IsInstanceOfType(kv1.Value)))
                      {
                          sbCachedKey = sbCachedKey.AppendFormat("{0}:{1};",kv.Key,
                              JsonConvert.SerializeObject(kv.Value, Formatting.None, new JsonSerializerSettings()
                              {
                                  NullValueHandling = NullValueHandling.Ignore,
                                  ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                              }));
                      }
                  }
      
                  _cachedKey = String.Format("{0}:{1}:{2}", GetType().Name, path, sbCachedKey.ToString());
              }
      
      
              if (!String.IsNullOrWhiteSpace(_cachedKey) && filterContext.HttpContext.Cache[_cachedKey] != null)
              {
                  filterContext.Result = (ActionResult)filterContext.HttpContext.Cache[_cachedKey];
              }
              else
              {
                  base.OnActionExecuting(filterContext);
              }
          }
      
          public override void OnActionExecuted(ActionExecutedContext filterContext)
          {
              if (!String.IsNullOrWhiteSpace(_cachedKey))
              {
                  filterContext.HttpContext.Cache.Add(_cachedKey, filterContext.Result, null,
                      DateTime.UtcNow.AddSeconds(Duration), Cache.NoSlidingExpiration,
                      CacheItemPriority.Default, null);
              }
      
              base.OnActionExecuted(filterContext);
          }
      }
      

      属性使用

      [OutputCacheComplex(typeof(DatacarMonitorSearchCriteriaModel), Duration = OutputCacheDurationInSeconds, Location = OutputCacheLocation.Server)]
      public async Task<JsonNetResult<DatacarMonitorDetailModel>> ReadMonitorDetailsJson([DataSourceRequest] DataSourceRequest request, DatacarMonitorSearchCriteriaModel criteria)
      { 
           //some really complicated code here
      }
      

      使用这个新属性,您可以指定用于缓存的类型[s],缓存键将根据其每个属性的值计算。

      【讨论】:

      • 你的方法 _types.AtLeastOnce() 是什么??
      • @leen3o AtLeastOnce(Expression) 方法只是一个 Enumerable 扩展方法,相当于 LINQ Any(Expression)
      【解决方案3】:

      对于对象,就可以了:

          [OutputCache(VaryByParam = "*", Duration = 60)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-16
        • 2018-10-06
        • 2014-10-30
        相关资源
        最近更新 更多