Заставить все области использовать один макет

88

У меня следующая структура проекта:

  • / Просмотры / Shared / _Layout;

  • / Areas / Area1 / Views / ControllerName / Index;

...

  • / Области / AreaN / Views / ControllerName / Index.

Есть ли способ заставить все области использовать _Layout в качестве базового макета ?

Есть ли способ сделать это без добавления файла _ViewStart (например, через конфигурацию маршрутизации)?

Смотрите также:

Как указать разные макеты в файле ViewStart для ASP.NET MVC 3?

Михаил
источник
Вот один хороший ответ и другой
Рафаэль Эмшофф

Ответы:

155

Вам просто нужно добавить файл с именем:

_ViewStart.cshtml

Под каждой папкой просмотра области:

/Areas/Area1/Views/_ViewStart.cshtml

И отредактируйте файл так, чтобы он указывал на корневой макет следующим образом:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Чтобы это работало, вам не нужно указывать значение в свойстве макета представления, если вы это сделаете, вы переопределите глобальный макет

Примечание: как упомянул Тони, вы можете редактировать свойство макета каждого представления, чтобы указывать на корневой макет, однако это не рекомендуемый способ сделать это, так как вы будете связывать свои представления с макетом и изменять его будет болезненно

Редактировать 1

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

Попробуйте погуглить о кастомах RazorViewEngineиRazorView

Эта статья может стать хорошей отправной точкой

http://weblogs.asp.net/imranbaloch/archive/2011/06/27/view-engine-with-dynamic-view-location.aspx

Я ничего подобного не делал, но надеюсь, что указываю вам в правильном направлении

Юпаол
источник
1
Есть ли способ сделать это без добавления файла "_ViewStart" (например, через конфигурацию маршрутизации)?
Михаил
2
В рамках маршрутизации я так не думаю. Это разные вещи. Маршрутизация отвечает за попытку сопоставить текущий URL-адрес запроса с маршрутом, зарегистрированным в RoutesTable, при нахождении соответствия создается IMvcRouteHandler, а затем IHttpHandler (MvcHandler) отвечает за обработку действия вашего контроллера. Как видите, это не имеет никакого отношения к представлениям или макетам. Это связано с тем, что маршрут не обязательно возвращает представление, он может возвращать json или xml. Так что маршрутизация - не самое подходящее место для реализации чего-то подобного.
Jupaol
Вы также можете добавить его _ViewStartпрямо в папку Area, чтобы применить его ко всем областям.
Артур
21

Расширяя ответ Jupaol ....

По крайней мере, в VS2013 файл _ViewStart.cshtml добавляется по умолчанию при создании области, поэтому он уже существует, и вы можете изменить содержимое, как он отмечает, чтобы указать на корень _Layout.cshtml. Затем вы можете удалить _Layout.cshtml в этой области, так как он больше не используется (и теперь является потенциальным источником путаницы).

Однако при этом любая маршрутизация, выполняемая в этом корневом _Layout.cshtml, должна будет учитывать области.
По умолчанию _Layout.cshtml имеет несколько помощников ActionLink, которые нужно немного изменить:

Добавьте параметр RouteValueDictionary к любым вызовам ActionLink, установив Area = "". Обратите внимание, что пустая строка относится к корневому уровню. Это позволит этим ссылкам работать правильно при вызове из области, но по-прежнему работать при вызове из корня.

например:

<li>@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)</li>
Роб Кэмпбелл
источник
2

Вы указываете макет, используя:

@ {Layout = "_Layout"; }

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

Не уверен, зачем нужно менять маршрутизацию, или, возможно, я не понимаю. Надеюсь это поможет :)

Тони
источник