VaryByParam завершается ошибкой, если param является списком

У меня есть это действие в MVC

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

который не может представить правильный HTML с URL-адресом, как

Это известная ошибка OutputCache в.NET, потому что не удается распознать 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<string> Там что-то еще глючит, но не стоило тратить больше усилий.

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

Временное решение

Я закончил тем, что создал свой собственный атрибут OutputCache после другого SO сообщения. Намного проще в использовании, и я могу наслаждаться остальным днем.

Метод Контроллера

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

Класс пользовательских запросов

Я унаследовал от List<string> так что я могу назвать переопределенным .ToString() метод в классе MyOutputcache, чтобы дать мне уникальную строку ключа кэша. Один только этот подход разрешил подобные проблемы для других, но не для меня.

[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);
    }
}
Другие вопросы по тегам