MVCsiteMapProvider: использование обрезки безопасности с выходным кешем возвращает пустую карту сайта

Я использую помощник Html MvcSiteMapProvider для создания панели навигации. Содержимое панели навигации зависит от прав посетителя, поэтому я использую обрезку безопасности, чтобы отображать только тот контент, на который у человека есть права. Для повышения производительности я пытаюсь кэшировать эту панель навигации.

Панель навигации создается в частичном представлении со следующим содержимым:

@Html.MvcSiteMap().Menu("MenuHelper", new { name = "MainMenu" })

Внутри файла макета он вызывается методом действия, который возвращает частичное представление:

[System.Web.Mvc.OutputCache(Duration = 10, VaryByCustom = "User")]
[ChildActionOnly]
public ActionResult MainMenu()
{
    return PartialView("MainMenu");
}

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

Возможно ли, что метод действия, который возвращает панель навигации, вызывается, когда данные авторизации недоступны, и, следовательно, возвращает поврежденную карту сайта?


person Hello It's me    schedule 15.12.2015    source источник


Ответы (1)


Если вы проанализируете исходный код для AuthorizeAttribute вы заметите, что он не предназначен для работы с дочерними действиями, вывод которых кэшируется (они делают все возможное, чтобы гарантировать, что дочерние действия, выходные данные которых кэшируются, вызовут исключение).

Конечно, это также не будет работать правильно, если у вас есть пользовательский AuthorizeAttribute, который переопределяет OnAuthorization, который не дублирует эту важную логику.

Однако есть несколько вещей, которые вы можете сделать, чтобы повысить производительность при использовании Security Trimming:

  1. Убедитесь, что ваши конструкторы внедрения просты, особенно на ваших контроллерах. Если у вас есть интенсивная обработка в ваших конструкторах, это может действительно замедлить работу (с MvcSiteMapProvider или без него, но Security Trimming делает это гораздо более очевидным).
  2. Если это недостаточно улучшает ситуацию и вы не используете пользовательский AuthorizeAttribute, вы можете использовать атрибут/свойство roles, чтобы продублировать логику своей роли в SiteMap и удалить AuthorizeAttributeAclModule из своей конфигурации (только внешний DI).

Дополнительные сведения см. в этом обсуждении.

person NightOwl888    schedule 16.12.2015
comment
Это все еще применимо, когда только действие, использующее макет, использует AuthorizeAttribute, а не дочернее действие? - person Hello It's me; 18.12.2015
comment
Я никогда не пытался использовать MvcSiteMapProvider с кэшированием вывода. Я предполагаю, что это, вероятно, не сработает. Он должен быть динамичным и меняться при каждом запросе. Кэширование вывода означает, что объект SiteMap никогда не будет вызываться, и никакая логика, которая должна выполняться при каждом запросе, не будет работать, эффективно обходя провайдеров фильтрации и видимости. - person NightOwl888; 19.12.2015