我在MVC中有这个 Action

[OutputCache(Duration = 1200, VaryByParam = "*")]
public ActionResult FilterArea( string listType, List<int> designersID, int currPage = 1 )
{
   // Code removed
}

无法使用 url 显示正确的 HTML,例如
  • http://example.com/en-US/women/clothing?designersID=158
  • http://example.com/en-US/women/clothing?designersID=158&designersID=13

  • 这是 .NET 中 OutputCache 的一个已知错误,导致无法使用列表参数识别 VaryByParam 还是我遗漏了什么?

    最佳答案

    我在 MVC3 中也有同样的问题,我相信它在 MVC5 中仍然是同样的情况。

    这是我的设置。

    要求

    POST,Content-Type:application/json,传入一个字符串数组作为参数

    { "options": ["option1", "option2"] }
    

    Controller 方法

    [OutputCache(Duration = 3600, Location = OutputCacheLocation.Any, VaryByParam = "options")]
    public ActionResult GetOptionValues(List<string> options)
    

    我尝试了 OutputCache 的所有可能选项,但它并没有为我缓存。绑定(bind)工作正常,使实际方法正常工作。我最大的怀疑是 OutputCache 没有创建唯一的缓存键,所以我什至从 System.Web.MVC.OutputCache 中提取了它的代码来验证。我已经验证它即使在传入 List<string> 的情况下也能正确构建唯一键。 那里的其他东西有问题,但不值得花更多的精力。

    OutputCacheAttribute.GetUniqueIdFromActionParameters(filterContext,
                    OutputCacheAttribute.SplitVaryByParam(this.VaryByParam);
    

    解决方法

    我最终在另一个 SO 帖子之后创建了我自己的 OutputCache 属性。更容易使用,我可以去享受一天的剩余时间。

    Controller 方法

    [MyOutputCache(Duration=3600)]
    public ActionResult GetOptionValues(Options options)
    

    自定义请求类

    我是从 List<string> 继承的,所以我可以调用 MyOutputcache 类中覆盖的 .ToString() 方法来给我一个唯一的缓存键字符串。仅这种方法就为其他人解决了类似的问题,但对我没有。

    [DataContract(Name = "Options", Namespace = "")]
    public class Options: List<string>
    {
        public override string ToString()
        {
            var optionsString= new StringBuilder();
            foreach (var option in this)
            {
                optionsString.Append(option);
            }
            return optionsString.ToString();
        }
    }
    

    自定义输出缓存类

    public class MyOutputCache : ActionFilterAttribute
    {
        private string _cachedKey;
    
        public int Duration { get; set; }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.Url != null)
            {
                var path = filterContext.HttpContext.Request.Url.PathAndQuery;
                var attributeNames = filterContext.ActionParameters["Options"] as AttributeNames;
                if (attributeNames != null) _cachedKey = "MYOUTPUTCACHE:" + path + attributeNames;
            }
            if (filterContext.HttpContext.Cache[_cachedKey] != null)
            {
                filterContext.Result = (ActionResult) filterContext.HttpContext.Cache[_cachedKey];
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }
    
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.HttpContext.Cache.Add(_cachedKey, filterContext.Result, null,
                DateTime.Now.AddSeconds(Duration), System.Web.Caching.Cache.NoSlidingExpiration,
                System.Web.Caching.CacheItemPriority.Default, null);
            base.OnActionExecuted(filterContext);
        }
    }
    

    关于asp.net-mvc-5 - 如果参数是列表,则 VaryByParam 失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24860685/

    10-11 16:20