【问题标题】:VaryByParam fails if a param is a list如果参数是列表,则 VaryByParam 失败
【发布时间】:2014-09-11 16:45:01
【问题描述】:

我在 MVC 中有这个动作

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

无法用类似 url 的方式显示正确的 HTML

这是 .NET 中 OutputCache 的已知错误导致无法识别带有列表参数的 VaryByParam 还是我遗漏了什么?

【问题讨论】:

  • 到底是什么问题?
  • 问题是,如果您尝试使用 2 个不同的视图获取 2 个不同的视图,系统会失败并获取您请求的第一个视图,因为如果参数是字符串列表,他不会改变 ByParam, int 或其他。 :(

标签: asp.net-mvc-5 outputcache varybyparam


【解决方案1】:

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

这是我的设置。

请求

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

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

控制器方法

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

我尝试了使用 OutputCache 的所有可能选项,但它并没有为我缓存。绑定对于实际工作的方法来说工作得很好。我最大的怀疑是 OutputCache 没有创建唯一的缓存键,所以我什至从System.Web.MVC.OutputCache 中提取了它的代码来验证。我已经验证,即使传入了 List&lt;string&gt;,它也能正确构建唯一键。那里有其他东西是错误的,但不值得花更多的精力。

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

解决方法

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

控制器方法

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

自定义请求类

我继承自 List&lt;string&gt;,因此我可以在 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();
    }
}

自定义 OutputCache 类

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

【讨论】:

  • 这可能是一个解决方案,但 MVC 代码中仍然存在错误。
猜你喜欢
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
相关资源
最近更新 更多