Кэширует ли Razor ViewEngine визуализированные HTML-коды? - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть пункт меню с двумя уровнями: у меня есть список отделов, и у каждого отдела есть список магазинов.

У меня есть меню, PartialView, которое перебирает Model (отделы) исоздает меню:

@model IEnumerable<Department>

<ul>
    @foreach (var department in Model)
    {
        <li>
            <a href="#">@Model.DepartmentName</a>
            <ul>
                @foreach (var store in department.Stores)
                {
                    <li><a href="some-url">@store.StoreName</a></li>
                }
            </ul>
        </li>
    }
</ul>

И вот как я вызываю Menu PartialView в моем _layout.cshtml:

@Html.Partial("Shared/_Menu", MyApplicationCache.departments) 

Как вы видите, я передаю ту же модель (изкеш) в PartialView на все запросы.

Есть ли в Razor ViewEngine внутренняя система кэширования, позволяющая распознать, что это представление уже создано (соответствует строке HTML) для этой модели?Или он перерисовывает (перекомпилирует) PartialView при каждом отдельном запросе?

Ответы [ 3 ]

0 голосов
/ 05 декабря 2018

На этот вопрос есть отличный ответ, который доказывает, что PartialViews не кэшируются, и эта ссылка , которая предлагается в комментариях, объясняет, как использовать [OutputCache] для частичного просмотра - это можно использовать с Html.Action() / Html.RenderAction() и отображает PartialViews как [ChildAction].

Кэширование PartialView как дочернего действия имеет смысл, но я не хотел отображать свое меню как [ChildAction], потому что я не хотел делатьОтдельный вызов для отображения меню, поэтому я в итоге и сделал:

Я использовал RazorEngine для рендеринга моего PartialView в HtmlString при запуске приложения и сохранит HtmlString в статическом состоянии.переменная (кеш).

public static class MenuCache
{
    private static readonly MvcHtmlString _menuMvcHtmlString;

    static MenuCache()
    {
        using (var context = ApplicationDbContext.Create())
        using (var razorEngine = RazorEngineService.Create(new TemplateServiceConfiguration()))
        {
            var repository = new MyRepository(context);
            var departments = repository.GetDepartments();

            // use razorEngine to render menu partial view into html string 
            // keep the htmlString in cache: _menuMvcHtmlString
            string menuPartialView = File.ReadAllText(HostingEnvironment.MapPath("~/Views/Shared/_Menu.cshtml"));
            string menuHtmlString = razorEngine.RunCompile(menuPartialView, "menuKey", null, departments);
            _menuMvcHtmlString = new MvcHtmlString(menuHtmlString);
        }
    }

    public static MvcHtmlString GetMenuHtmlString()
    {
        return _menuMvcHtmlString;
    }
}

Я также создал метод Customized HtmlHelper, который будет возвращать HtmlString для меню:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString MyMenu(this HtmlHelper html)
    {
        return MenuCache.GetMenuHtmlString();
    }
}

Теперь на моей странице _Layout я могу использовать настроеннуюHtmlHelper для отображения меню:

@Html.MyMenu()
0 голосов
/ 06 декабря 2018

Повторный рендеринг и повторная компиляция в ASP.Net MVC очень сильно отличаются.Хотя большинство ответов здесь верны, представление компилируется только один раз (за исключением режима отладки, где он компилируется каждый раз, так что вы можете изменить представление, нажать «Обновить» и увидеть изменение, или если отметка времениизменения в файле в производстве).Он скомпилирован в класс времени выполнения, который наследуется от WebViewpage (без ViewModel) или WebViewPage<T> (имеет ViewModel типа T).

Класс создается для каждого необходимого представления (поэтому, если вы использовали один и тот же частичный несколько раз, вы должны создавать экземпляр каждый раз), модель заполняется, и метод execute () вызывается для создания /Поток HTML для клиента.Представление никогда не может быть кэшировано для каждой модели, поскольку это сложно сделать, и вместо этого команда MVC решила разрешить настройку кэширования для каждого метода контроллера, а не для WebViewPage.

@ ErikPhilips, большое спасибо за это. Итак, представление компилируется только один раз (независимо от того, используем ли мы OutputCache или нет)?Это метод execute, который рендерит класс времени выполнения в HtmlString, и это рендеринг, который выиграл бы от кеширования?

Сорта, но он гораздо более сложный, простой и сложный, чем этот.

Дополнительно - Выходной кэш основан на методе контроллера.Таким образом, если конфигурация выходного кэша определяет, что вызов может использовать кэшированную версию, метод контроллера никогда не называется .Вот где огромный прирост производительности.Представьте, что нет вызова для вызова БД / внешнего API, в этом нет необходимости.Вы можете настроить кеш так, чтобы он видел id=1 кешировать его в течение 30 минут.Теперь любой, кто вызывает этот метод с авторизацией и id=1, получает кешированную строку / html.

Проще - вы добавляете OuputCacheAttribute в метод, настраиваете его, и все готово.Довольно чертовски прост в настройке.

Сложно - Кэширование может быть более сложным , потому что вы можете визуализировать другие методы контроллера, используя Html.Action() (Html.Partial(), если вам не нужен макет для вашегочастичный) или предпочтительный Html.RenderAction(); (Html.RenderPartial(), если вам не нужен макет).Раньше была проблема с кэшированием пончиковых отверстий (рекомендуется чтение), но это было исправлено в течение длительного времени.

0 голосов
/ 29 ноября 2018

PartialView перерисовывается при каждом отдельном запросе, при условии, что к Controller или к его методу действия не применен OutputCacheAttribute.

Если вам нужно кэширование вывода,вам нужно установить это явно через OutputCacheAttribute, см. документацию .

. Вы можете легко проверить это, выдав DateTime, например.через пункт меню, как показано ниже.
При каждом запросе будет отображаться новое значение, подтверждающее его повторное отображение.

<li><a href="#">@DateTime.Now</a></li>

Полное меню:

@model IEnumerable<Department>

<ul>
    @foreach (var department in Model)
    {
        <li>
            <a href="#">@Model.DepartmentName</a>
            <ul>
                <li><a href="#">@DateTime.Now</a></li>
                @foreach (var store in department.Stores)
                {
                    <li><a href="some-url">@store.StoreName</a></li>
                }                
            </ul>
        </li>
    }
</ul>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...