#asp.net-mvc-3 #layout #razor
#asp.net-mvc-3 #макет #razor
Вопрос:
В веб-приложении .NET Razor я пытаюсь программно установить Layout
. Я не могу использовать _ViewStart.cshtml
и не имею обыкновения устанавливать @{ Layout = "..." }
на каждой странице. Это то, что я придумал:
Базовый WebViewPage
класс:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T>
{
private object _layout;
public new dynamic Layout { get { return _layout; } }
public override void InitHelpers()
{
base.InitHelpers();
_layout = "~/Themes/" Settings.Theme "/Views/_Layout.cshtml";
}
}
И в приложении web.config
я указываю all view для использования этой базовой страницы. Но Layout
, похоже, никогда не используется. Что здесь может быть не так?
Ответ №1:
WebViewPage
Класс наследует от WebPageBase
, который имеет свойство с именем Layout
, подобное:
public override string Layout { get; set; }
Вы можете переопределить Layout
свойство или изменить свою логику _layout для достижения своей цели. Например:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T> {
// set this modifier as protected, to make it accessible from view-pages
protected string _layout{
get {
return base.Layout;
}
set {
base.Layout = value;
}
}
public override void InitHelpers() {
base.InitHelpers();
_layout = "~/Themes/" Settings.Theme "/Views/_Layout.cshtml";
}
}
и / или на странице просмотра вы также можете установить его:
@{
_layout = "_Your_Special_Layout.cshtml";
}
ОБНОВЛЕНИЕ: использование флага, чтобы избежать переполнения стека при назначении _layout более одного раза:
public abstract class SitePage<T> : System.Web.Mvc.WebViewPage<T> {
public bool LayoutAssigned {
get {
return (ViewBag.LayoutAssigned == true);
}
set {
ViewBag.LayoutAssigned = value;
}
}
// set this modifier as protected, to make it accessible from view-pages
protected string _layout{
get {
return base.Layout;
}
set {
base.Layout = value;
}
}
public override void InitHelpers() {
base.InitHelpers();
if(!LayoutAssigned) {
_layout = "~/Themes/" Settings.Theme "/Views/_Layout.cshtml";
LayoutAssigned = true;
}
}
}
Комментарии:
1. Похоже, это вызывает переполнение стека. Когда Layout.cshtml содержит partialview, снова вызывается InitHelpers и устанавливает макет, затем Layout.cshtml, похоже, снова инициализируется и снова устанавливает макет и т.д.
2. Вы правы. Вы можете что-то сделать, чтобы решить эту проблему. Один из них использует логический флаг, чтобы проверить,
Layout
присвоен или нет. Который я использовал в своем проекте, заключается в том, что у меня есть 3 базовых класса для layouts, view-pages и partial-views. Также вы можете найти любые другие способы, специальные для вашего проекта3. Я плохо говорю по-английски. Извините, если мои предложения непонятны:D
4. Ваш английский в порядке: D Спасибо, что помогли мне начать, настройка a
bool
вContext.Items
работает нормально (или ViewBag, как в вашем exmaple). Спасибо!5. Обнаружил это при попытке исправить проблему с stackoverflow — я упомяну, что вышеупомянутое помогло, но не совсем сработало для меня. После долгих экспериментов я обнаружил, что мне пришлось переопределить ExecutePageHierchy, а не InitHelpers.
Ответ №2:
Я пытался достичь того же самого только сейчас, внедрив пользовательскую WebViewPage, однако изменив WebViewPage.Макет в моем пользовательском классе не оказал никакого эффекта (как вы также обнаружили).
В конце концов я закончил тем, что изменил свой _ViewStart.cshtml, чтобы иметь этот код:
@{
this.Layout = this.Request.QueryString["print"] == "1"
? "~/Views/Layout/_Print.cshtml"
: "~/Views/Layout/_Layout.cshtml";
}
Возможно, он реализован не так, как вы хотели, но он, безусловно, сохраняет все сухим, и это главное.