Программно заданный макет .NET MVC 3

#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";
}
  

Возможно, он реализован не так, как вы хотели, но он, безусловно, сохраняет все сухим, и это главное.