Как получить значение макета по умолчанию из _ViewStart.cshtml в MVC/Razor

У меня есть методы расширения для класса MVC Controller, который должен знать, что такое текущий файл макета по умолчанию (т.е. значение из _ViewStart.cshtml).

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

e.g.

public static void RenderMode(this Controller controller)
{
     if (!controller.Request.IsAjaxReuest())
     {
         controller.ViewBag.Layout = ????????;
     }
}

Итак, вопрос в том, как получить из кода значение макета страницы по умолчанию?


person Gone Coding    schedule 22.08.2014    source источник
comment
Файл _ViewStart всегда является первым представлением, которое выполняется объектом RazerView. Это internal readonly поле ViewStartFileName внутри RazorViewEngine. Файл _ViewStart может определять для каждой папки макет по умолчанию для всех представлений ниже. Внутри глобального фильтра действий было бы проще условно изменить макет. Проблема в том, что контроллер еще не знает о созданном представлении.   -  person Andreas    schedule 22.08.2014
comment
@Andreas: Значит, в принципе, нет? Я не могу понять. :)   -  person Gone Coding    schedule 22.08.2014
comment
Не обошлось без подвохов ;-) stackoverflow.com/q/7575577/1484933   -  person Andreas    schedule 22.08.2014
comment
@Андреас: Спасибо за информацию. Обходной путь опубликован ниже. Дайте мне знать, если вы когда-нибудь найдете лучшую альтернативу. :)   -  person Gone Coding    schedule 22.08.2014


Ответы (1)


Согласно комментарию Андреаса (спасибо), необходимая настройка скрыта в классе RazorViewEngine и недоступна.

Обновление, сентябрь 2015 г. — новое решение!

Недавно мы нашли лучший способ сделать это без инвазивных изменений в любом коде действия.

Шаги:

  • Наследовать все контроллеры от общего класса BaseController.
  • Добавьте метод переопределения OnActionExecuting в файл BaseController.
  • Вызовите RenderMode() из этого метода, так что это произойдет для всех запросов до того, как действие будет вызвано.
  • Измените RenderMode() на установку ViewBag.Layout = null для запросов страниц Ajax.
  • Внутри _ViewStart.cshtml добавьте код, чтобы задать для макета значение ViewBag.

BaseController.cs — режим визуализации()

public void RenderMode(string layout)
{
    if (IsPartialPage)
    {
        // Wipe any existing layout page
        ViewBag.Layout = null;
        return;
    }
    ViewBag.Layout = layout;
}

Виевстарт.cshtml

@{
    Layout = (string)ViewContext.Controller.ViewBag.Layout;
}

Конечным результатом является то, что вы можете вернуть View() или PartialView() как обычно, и представление будет отображаться как полное или частичное представление вместо этого на основе проверки "ajax", выполненной перед выполнением действия. Это значительно упростило наши веб-сайты, так как мы можем использовать больше стандартного шаблонного кода как есть.


Предыдущее решение (устарело)

Поэтому мой обходной путь заключается в том, чтобы передать макет по умолчанию методу расширения RenderMode:

i.e.

public static void RenderMode(this Controller controller, layout)
{
     if (!controller.Request.IsAjaxReuest())
     {
         controller.ViewBag.Layout = layout;
     }
}

и вызовите из любого контроллера, подобного этому (или используя константу, известную приложению):

public ActionResult SomeAction()
{
    var vm = new SomeViewModel();
    RenderMode("~/views/shared/_MainLayout.cshtml");
    return PartialView(vm);
}

Конечным результатом является частичное представление при вызове из Ajax или полное представление с использованием _mainLayout.cshtml при непосредственном вызове.

person Gone Coding    schedule 22.08.2014