Где и как связан файл макета _ViewStart.cshtml?

199

Вот файл About.cshtml из шаблона MVC 3 по умолчанию:

@{
    ViewBag.Title = "About Us";
}

<h2>About</h2>
<p>
     Put content here.
</p>

Я ожидаю, что ссылка на файл _ViewStart будет найдена в About.cshtml, но, очевидно, это не так.

Я посмотрел global.asaxи web.config, но я не могу выяснить, как About.cshtmlфайл "связан" с макетом из файла _ViewStart.

Все работает как положено, я просто хотел бы знать, что происходит под капотом ...

Kman
источник

Ответы:

237

Из блога ScottGu :

Начиная с версии бета-версии ASP.NET MVC 3, вы можете добавить файл с именем _ViewStart.cshtml (или _ViewStart.vbhtml для VB) в папку \ Views вашего проекта:

Файл _ViewStart можно использовать для определения общего кода представления, который вы хотите выполнить в начале рендеринга каждого представления. Например, мы могли бы написать код в нашем файле _ViewStart.cshtml, чтобы программно установить свойство Layout для каждого представления в файл SiteLayout.cshtml по умолчанию:

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

Важно: поскольку _ViewStart.cshtml позволяет нам писать код, мы можем при желании сделать нашу логику выбора Layout более богатой, чем просто базовый набор свойств. Например: мы могли бы изменить шаблон макета, который мы используем, в зависимости от того, какой тип устройства обращается к сайту, - и иметь оптимизированный макет телефона или планшета для этих устройств, а также макет, оптимизированный для настольных компьютеров, для ПК / ноутбуков. Или, если бы мы создавали систему CMS или общее общее приложение, которое используется несколькими клиентами, мы могли бы выбирать разные макеты для использования в зависимости от клиента (или его роли) при доступе к сайту.

Это обеспечивает большую гибкость пользовательского интерфейса. Это также позволяет вам легче написать логику вида один раз и избежать повторения в нескольких местах.

Также посмотрите это .

Джим Толлан
источник
14
То есть это более или менее «жестко закодированная» функция MVC3? Мне не нужно менять его на другую страницу по умолчанию, просто любопытно, как она была настроена. Спасибо, что все разобрались :)
Kman
2
Kman - Hardcoded, условно (выберите другую «ручку» здесь :)) - так что да, именно так. рад, что это очистило туман
Джим Толлан
Вам может понадобиться не только ваша папка "Views". Если вы добавляете пользовательский RazorViewEngine для организации представлений в другие папки, вы должны также включить файл в корень этих папок альтернативного представления. Например, я переместил все представления шаблона Inspinia в папку и запустил это в движке представления ViewLocationFormats = ViewLocationFormats.Union(new string[] { "~/Inspinia/ExampleViews/{1}/{0}.cshtml" }).ToArray();. В результате мне пришлось добавить копию моего файла _ViewStart.cshtml в «~ / Inspinia / ExampleViews», в противном случае он не был выбран и макет не был установлен.
Триынко
2
Если в папке «Представления» есть подпапки, можете ли вы поместить _ViewStartв каждую подпапку ссылку, которая будет ссылаться на представления в этой подпапке?
toddmo
35

В более общем смысле эта способность инфраструктуры MVC «знать» о _Viewstart.cshtml называется «Кодирование по соглашению».

Соглашение по конфигурации (также известное как кодирование по соглашению) - это парадигма разработки программного обеспечения, которая стремится уменьшить количество решений, которые должны принять разработчики, получая простоту, но не обязательно теряя гибкость. Фраза по сути означает, что разработчику нужно только указать нетрадиционные аспекты приложения. Например, если в модели есть класс Sale, соответствующая таблица в базе данных по умолчанию называется sales. Только в случае отклонения от этого соглашения, например, при вызове таблицы «products_sold», нужно написать код, относящийся к этим именам.

Википедия

В этом нет магии. Он только что был записан в базовую кодовую базу инфраструктуры MVC и поэтому является тем, о чем MVC «знает». Вот почему вы не можете найти его в файлах .config или где-либо еще; это на самом деле в коде MVC. Однако вы можете переопределить, чтобы изменить или обнулить эти соглашения.

RISM
источник
13
Если MVC знает об этом, то почему Visual Studio не знает и не указывает мне на это? Если кодирование по соглашению означает, что материал работает до тех пор, пока вы не нарушаете соглашение, это отчасти отстой ...
Арне Эвертссон,
Не нарушать соглашение является своего рода точкой. AKAIK Ruby on Rails также следует этой парадигме.
Умар Фарук Хаваджа
+1 Раиф. Нет смысла защищать плохо документированное «кодирование по соглашению». Я мог бы сказать это о любом моем обратном коде. «Что? Вы не ожидали, что он рухнет, когда он достиг 33? Все знают, что вы пропустите 33». К сожалению, пробел в документации для ASP.NET MVC огромен. Единственные документы MS создаются автоматически без кратких сводок по внутренним источникам.
Шеннон
6
Соглашение о конфигурации не означает, что вы не можете изменить его. ДОЛЖНА быть доступна конфигурация, чтобы можно было указать имя и местоположение этого файла. Там может быть очень хорошо, но кто знает, что это такое. Люди используют мантру «соглашение о конфигурации», чтобы покрыть множество неверных решений в кодовой базе, и это меня бесит, как парня, который после этого поддерживает некачественный документированный беспорядок, который «просто работает» (но Не дай бог, ты что-нибудь изменишь - ты будешь часами разбираться, как ты все сломал).
Роберт С. Барт,
3
@AidenStrydom Я не согласен. Принятый ответ на самом деле говорит мне, как использовать _ViewStart. Этот ответ просто говорит о концепции дизайна. Я пришел сюда за информацией о _ViewStart, а не о том, почему Visual Studio ничего не говорит мне о _ViewStart.
Милли Смит
23

Просто еще одна мысль.

Если вы хотите иметь свой собственный cshtmlфайл в качестве общего шаблона, вы можете сделать это следующим образом

Внутри вашего _viewstart.cshtmlвы можете упомянуть свой общий cshtmlфайл.

@{Layout = "~/Views/Shared/_Layout.cshtml";}
user2515392
источник
14

Исходный код гораздо лучше, чем документация.

Ссылаясь на код MVC 6 от Github, у нас есть несколько файлов, представляющих интерес

----Обновить----

Из-за изменений в структуре источника информацию о том, как собираются страницы просмотра, теперь можно найти в RazorViewEngine.cs. ищет функцию «GetViewStartPages».

----/Обновить----

Чтобы ответить, как они вступают в игру, посмотрите на RazorView , который, как я считаю (из-за IView), связан с конвейером MVC. Этот файл имеет метод RenderAsync, который вызывается из конвейера MVC для визуализации запрошенного представления.

RenderAsync выполняет вызовы RenderPage И ТОГО RenderLayout (ЗАМЕТЬТЕ ЗАКАЗ). Сначала RenderPage выполняет вызовы для работы с файлами Viewstart (обратите внимание, что во множественном числе может быть более одного файла _viewstart).

Таким образом, запрашиваемую информацию можно получить из функции RenderViewStartAsync в файле RazorView.cs в пространстве имен Microsoft.AspNet.Mvc.Razor.

Фрисон Александр
источник
7

Это может добавить некоторую дополнительную информацию к этому вопросу сейчас (2016 ala MVC4, MVC5).

Механизм Razor находит и запускает код в _ViewStart.cshtml перед любым другим кодом, который находится в том же каталоге или подкаталоге, где находится _ViewStart.cshtml. .

Любое представление может переопределить свойство Layout или любое из его значений.

Просто подумал, что мог бы добавить немного больше информации, чтобы показать вам, почему это _ViewStart.

Если вы получите ILSpy и изучите код в RazorViewEngine (System.Web.Mvc.dll), вы увидите, что сам код ссылается на это имя.

_ViewStart в System.Web.Mvc.dll

Вы можете видеть, что RazorViewEngine ищет файл с таким именем:

бритвенный код

RazorViewEngine.ViewStartFileName = "_ViewStart";
raddevus
источник
3
это то, что я искал, я ненавижу «не знаю», что происходит в моем проекте, потому что я также делаю свои собственные шаблоны для VS, и этот файл, который только что вышел из воздуха, был очень неудобен для понимания
Себастьян 506563
1

Если вы хотите иметь общий макет для своих страниц, вам нужно определить общий макет и связать представление с макетом, мы должны установить свойство макета для каждого вида, это нарушает принцип СУХОЙ (не повторять себя). Для этого .Net Framework предоставляет файл "_ViewStart.cshtml", расположенный внутри папки просмотра. Мы размещаем информацию о макете в файле "_ViewStart.cshtml", и каждое представление по умолчанию использует эту информацию о макете. Если вы хотите предоставить какую-то другую информацию о макете, предположим, что на вашем домашнем экране вы можете создать новый «_ViewStart.cshtml» со ​​ссылкой на этот макет и поместить его в папку «Home View».

KamalDeep
источник
1

Краткий ответ : ViewStarts запускаются первыми, когда визуализируется любое представление. Длинная история ниже:

История создания единого файла просмотра:

  1. ViewStart объединяется с ViewImports и затем выполняется как один файл. Обратите внимание, что ViewImports всегда объединяется с любым файлом cshtml, включая файл ViewStart. Его цель - абстрагировать операторы @using и другие общие директивы.
  2. Выходные данные ViewStart (такие как Layout и ViewData) становятся доступными для конкретного файла View.
  3. Внутри файла View, если переменная Layout равна / становится пустой, тело представления визуализируется и конечный результат доставляется пользователю.
  4. Если переменная Layout равна / становится ненулевой, выполнение перемещается в файл макета, который, в свою очередь, объединяется с ViewImports как один файл, а затем в операторе @RenderBody () внутри файла макета выполнение возвращается обратно в файл представления. который снова сливается с ViewImports, а выходные данные объединяются с файлом макета в месте расположения @RenderBody (), и окончательный результат наконец доставляется пользователю.

Надеемся, что это заставит вас осознать, что на самом деле происходит внутри неизвестных загадок жизненного цикла вашей программы.

Шади Намроути
источник