Asp.Net MVC 3 Частичное кэширование вывода страницы Не соблюдение настроек конфигурации

У меня есть простой частичный вид, который я просматриваю в своем основном представлении с помощью:

 @Html.Action("All", "Template")

На моем контроллере у меня есть это:

    [OutputCache(CacheProfile = "Templates")]
    public ActionResult All()
    {
        return Content("This stinks.");
    }

И в моей конфигурации это:

<caching>
  <outputCacheSettings>
    <outputCacheProfiles>
      <clear/>
      <add name="Templates" duration="3600" varyByParam="none"/>       
    </outputCacheProfiles>
  </outputCacheSettings>
  <outputCache  enableOutputCache="false" enableFragmentCache="false" />
</caching>

Это приведет к сбою во время выполнения с исключением:

Ошибка выполнения дочернего запроса для обработчика 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper

И внутреннее исключение:

Продолжительность должна быть положительным числом

Теперь, очевидно, он не подбирает мои настройки web.config, потому что если я его сменил на:

[OutputCache(Duration = 3600)]

Он будет работать, но также заметьте в моем web.config, я отключил enableOutputCache и enableFragmentCache, но не соблюдает эти настройки.

Любопытно, что в нормальном режиме эти настройки работают нормально, так что же это о частичных представлениях, которые нарушают это? Я что-то упускаю? Гу говорит, что это должно работать нормально... Короче говоря, он должен соблюдать настройки кэширования в web.config, а если нет, то почему?

Ответ 1

Итак, я потратил минуту и ​​посмотрел на источник MVC 3. Первое, что пришло ко мне, это было немного взломанным. В основном потому, что они повторно используют атрибут, который работает в одной ситуации с соблюдением всех свойств и настроек конфигурации, а затем в сценарии действий с детьми просто игнорирует все эти настройки и разрешает только VaryByParam и Длительность.

Как можно было бы понять, что поддерживается, вне меня. Поскольку исключение, которое они хотят выбросить, которое говорит, что Неподдерживаемая настройка никогда не будет выбрано, если вы не указали продолжительность и значение VaryByParam

Вот основная часть кода, которая пахнет:

if (Duration <= 0) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_InvalidDuration);
}

if (String.IsNullOrWhiteSpace(VaryByParam)) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_InvalidVaryByParam);
}

if (!String.IsNullOrWhiteSpace(CacheProfile) ||
    !String.IsNullOrWhiteSpace(SqlDependency) ||
    !String.IsNullOrWhiteSpace(VaryByContentEncoding) ||
    !String.IsNullOrWhiteSpace(VaryByHeader) ||
    _locationWasSet || _noStoreWasSet) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_ChildAction_UnsupportedSetting);
}

Я не уверен, почему это не вызвано в документации, но даже если бы это было api, или, по крайней мере, выбросить правильное исключение.

Короче говоря, работает частичное кэширование вывода, BUTT не похоже, что вы тоже захотите. Я буду работать над исправлением кода и соблюдением некоторых параметров, таких как включен.

Update: Я исправил текущую реализацию, по крайней мере, для своей ситуации с учетом включенного флага и разрешения профилей кэша из web.config. Подробно в моем сообщении в блоге.

Ответ 2

Здесь более простой подход, если:

  • Основная цель состоит в том, чтобы отключить кеш при отладке, а включить его во время развертывания
  • У вас нет сложных политик кэширования.
  • У вас нет сложной системы развертывания, которая опирается на синтаксис кэширования Web.config
  • Идеально, если вы уже используете веб-преобразования XDT

Все, что я сделал, был создан новый атрибут "DonutCache".

[DonutCache]
public ActionResult HomePageBody(string viewName)
{
    var model = new FG2HomeModel();

    return View(viewName, model);
}

К сожалению, вы можете инициализировать только [Attribute] с константой, поэтому вам нужно инициализировать атрибут в его конструкторе. Примечание. Это не мешает вам устанавливать параметр variableByParam в объявлении [DonutCache].

class DonutCacheAttribute : OutputCacheAttribute
{
    public DonutCacheAttribute()
    {
        Duration = Config.DonutCachingDuration;
    }
}

Здесь я просто инициализирую атрибут из моего web.config с помощью статического свойства:

<appSettings>
    <add key="DonutCachingDuration" value="5"/> 
</appSettings>


public static class Config {
    public static int DonutCachingDuration
    {
        get
        {
            return int.Parse(ConfigurationManager.AppSettings["DonutCachingDuration"]);
        }
    }
}

Затем, конечно, вы можете использовать веб-преобразование XDT, которое вы уже используете, чтобы изменить это значение