Для тех, кто не читал статью о синтаксисе Razor – крайне рекомендую, хотя и постараюсь здесь не использовать слишком много его “фишек”. Также дальнейшее повествование подразумевает некоторое знакомство с технологией ASP.NET MVC.
Установка ASP.NET MVC 3 RC
Для работы с MVC 3 Release Candidate потребуется, для начала, его установить. Из важных моментов – если установлен Async CTP, отладка работать не будет, сравнительно полный список известных проблем – в Release Notes (забыли, например, упомянуть замену параметра optional на required для RenderSection).Если есть желание ознакомиться с исходным кодом для этой статьи – есть архив (всего 34KB) на google docs.
Для тех, кто пользуется ReSharper и его Intellisense есть не очень приятная новость. Пока (до выхода ReSharper 6) поддержка Intellisense в Razor ограничена (работает, когда в явном виде используешь Ctrl+Space, иногда требуется набрать первую букву). Тем, кого это сильно расстраивает, можно посоветовать переключиться в настройках ReSharper на Visual Studio Intellisense (Ctrl+Alt+Space будет по-прежнему вызывать ReSharper Intellisense).
Создание нового проекта
Для создания проекта необходимо в списке проектов выбрать ASP.NET MVC 3 Web Application:
![Создание нового проекта MVC Создание нового проекта MVC](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgd-q1dEI/AAAAAAAAAN0/PEZBctmINRE/Mvc3Razor_NewProject_thumb%5B2%5D.png?imgmax=800)
После этого на ваш выбор будет предложено два варианта – создать пустой проект или “Internet Application”. Для тех, кому MVC в новинку, однозначно рекомендую последний вариант (полезно посмотреть на реализацию Account). И, для того, чтобы получить View на основе Razor, имеет смысл оставить этот View Engine (по крайней мере, у меня он был выбран по умолчанию, не уверен на 100% относительно установки на “чистую” студию):
![Настройка нового проекта MVC Настройка нового проекта MVC](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgeyqNPAI/AAAAAAAAAN8/Ra7QAw1efKM/Mvc3Razor_NewProject2_thumb%5B2%5D.png?imgmax=800)
Для начала, тестовый проект создавать необязательно (тем более, что я сейчас пользуюсь NUnit, который, судя по всему, в этом диалоге не поддерживается).
Создав проект, получим следующую структуру для View:
![новый проект в SolutionExplorer новый проект в SolutionExplorer](http://lh3.ggpht.com/_TMDEK3HEqwk/TPwgfggIK5I/AAAAAAAAAOE/JTbykwQdkBY/Mvc3Razor_SolutionExplorer_thumb%5B3%5D.png?imgmax=800)
Обратите внимание на новые симпатичные иконки, довольно лаконично отражающие синтаксис Razor :) А если перейти к более серьезным вещам – особый интерес для нас представляют _Layout.cshtml, _ViewStart.cshtml и _LogOnPartial.cshtml. Подробности о них далее.
Если вы пока еще не используете в разработке ASP.NET MVC и создали проект типа “Internet Application”, то можете запустить его по Ctrl+F5 и посмотреть на получившееся элементарное приложение. Кстати, несмотря на его элементарность, подключив к нему базу пользователей вы заодно получите работающую страницы регистрации, логина и смены пароля. И еще один мелкий, но приятный бонус – вполне нормальный для простых приложений CSS.
Layout
Честно говоря, мне сложно использовать вместо “Layout” русскоязычные аналоги (разметка/компоновка/схема/макет) – другие ассоциации, поэтому оставлю как есть.Как вы знаете, в ASP.NET есть “master page”, который позволяет достаточно удобно организовывать расположение элементов на странице. В случае с Razor это Layout.
Для нашего проекта Layout по умолчанию содержится в файле _Layout.cshtml. Хочу обратить ваше внимание на то, что название этого файла никак не влияет на поведение по умолчанию – он используется для всех View, потому что указан в файле _ViewStart.cshtml, но об этом позже.
Содержимое файла _Layout.cshtml в новом проекте следующее:
![пример содержимого _Layout.cshtml пример содержимого _Layout.cshtml](http://lh3.ggpht.com/_TMDEK3HEqwk/TPwggWmRs3I/AAAAAAAAAOM/htgiZsfAZEY/Mvc3Razor_NewProjectLayout_thumb%5B1%5D.png?imgmax=800)
Рассмотрим значимое содержимое этого файла (на тексте и стилях заострять внимание не буду):
- “_LogOnPartial” – это подключение Partial View для отображения статуса относительно входа в систему. Ссылается на файл _LogOnPartial.cshtml, выводящий стандартное приветствие или ссылку для входа.
- ActionLink – ссылки на методы контроллера HomeController, оформленные с помощью CSS в виде горизонтального меню.
- RenderBody – директива, которая “рисует”, собственно, тот View, для которого работает данный Layout.
Использование нескольких Layout
Иногда может потребоваться использование нескольких layout (например, для администрирования и просмотра сайта). В качестве примера изменим отображение страницы about.Создадим layout для всплывающих окон, добавив файл _PopupLayout.cshtml со следующим содержанием:
![пример содержимого PopupLayout.cshtml пример содержимого PopupLayout.cshtml](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwghS63bpI/AAAAAAAAAOU/s0KpiTk2DJk/Mvc3Razor_PopupLayout_thumb%5B2%5D.png?imgmax=800)
Для файла About.cshtml, зададим новый layout – переопределим заданный по умолчанию непосредственно в заголовке нашего View:
![About layout About layout](http://lh3.ggpht.com/_TMDEK3HEqwk/TPwghyOHFKI/AAAAAAAAAOc/M20eAi_Bpyk/Mvc3Razor_AboutLayout_thumb%5B1%5D.png?imgmax=800)
А в основном layout поменяем ссылку на “About”:
![модификация ссылки для About модификация ссылки для About](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgixa1AOI/AAAAAAAAAOk/_yQlKfw_Cac/Mvc3Razor_AboutLink_thumb%5B1%5D.png?imgmax=800)
Теперь, запустив приложение и нажав в меню “About” получим всплывающее окно без меню и ссылки для Logon, за счет использования другого layout.
Partial Views и секции
При использовании Razor у нас есть еще две возможности для создания достаточно сложного Layout – Partial Views и секции.Первое понятие – Partial Views – должно быть хорошо знакомо тем, кто уже использует MVC. Для тех, кто его еще не использует – это некий аналог ascx-файлов. В качестве примера уже упоминался _LogOnPartial.cshtml (подключение описано выше в файле _Layout.cshtml). Его содержимое выглядит настолько просто, насколько это возможно (не выделяя специальные методы):
![пример содержимого LogOnPartial пример содержимого LogOnPartial](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgjrgu1yI/AAAAAAAAAOs/6qow9_aSrnI/Mvc3Razor_LogOnPartial_thumb%5B1%5D.png?imgmax=800)
Секции – это, по сути, аналог ContentPlaceHolder. Иными словами, вы описываете вызов RenderSection по названию в файле _Layout.cshtml, а во View описываете секцию. Есть возможность вызвать метод RenderSection с параметром required = false, тогда не будет возникать ошибки при отображении страниц, где эта секция не описана.
Так выглядит отображение секции (в этом примере есть как обязательная, так и необязательная секции):
![пример вызова RenderSection пример вызова RenderSection](http://lh4.ggpht.com/_TMDEK3HEqwk/TPwgkcAenZI/AAAAAAAAAO0/oHKbB4be3p4/Mvc3Razor_RenderSection_thumb%5B1%5D.png?imgmax=800)
Пример, естественно, надуманный – обычно footer одинаковый для всех страниц. А так выглядит соответствующая обязательная секция в файле Index.cshtml:
![пример секции в Razor пример секции в Razor](http://lh4.ggpht.com/_TMDEK3HEqwk/TPwglYUyEnI/AAAAAAAAAO8/fEDgekrD-Ps/Mvc3Razor_Section_thumb%5B1%5D.png?imgmax=800)
Вложенный Layout
Теперь, чтобы показать возможность создавать действительно сложный Layout, приведем пример, когда они (Layout – страницы, аналог master page) вложенные. Допустим, нам захотелось разнести вышеупомянутый _PopupLayout.cshtml на две структурных части – нет ничего проще.Так будет выглядеть файл _PopupCommonLayout.cshtml:
![пример содержимого _PopupCommonLayout.cshtml пример содержимого _PopupCommonLayout.cshtml](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgmOLACeI/AAAAAAAAAPE/Dn3HLonQOHc/Mvc3Razor_PopupCommonLayout_thumb%5B1%5D.png?imgmax=800)
А так будет выглядеть файл _PopupLayout.cshtml:
![пример вложенного Layout пример вложенного Layout](http://lh6.ggpht.com/_TMDEK3HEqwk/TPwgnQE4_JI/AAAAAAAAAPM/-S4k08Lb4Kg/Mvc3Razor_PopupLayout2_thumb%5B4%5D.png?imgmax=800)
Серверные комментарии
Теперь, о более элементарных вещах :)Наверняка вы знаете, что иногда обычных комментариев на странице недостаточно, и необходимо использовать серверные. Теперь Razor использует, на мой взгляд, максимально простой синтаксис для серверных комментариев – @* *@. Выглядит это так:
![Razor - пример серверных комментариев Razor - пример серверных комментариев](http://lh6.ggpht.com/_TMDEK3HEqwk/TPwgn_QyEHI/AAAAAAAAAPU/EzG8dzObH3k/Mvc3Razor_ServerSideComments_thumb%5B1%5D.png?imgmax=800)
При этом, внутри кода в Razor можно пользоваться как обычными комментариями:
![Razor - пример комментариев внутри блока кода Razor - пример комментариев внутри блока кода](http://lh6.ggpht.com/_TMDEK3HEqwk/TPwgpPJFBMI/AAAAAAAAAPc/dviVUV_Dht4/Mvc3Razor_InsideComments_thumb%5B1%5D.png?imgmax=800)
Так и серверными (обратите внимание на подсветку C# кода для закрывающей скобки):
![Razor - пример серверных комментариев внутри блока кода Razor - пример серверных комментариев внутри блока кода](http://lh5.ggpht.com/_TMDEK3HEqwk/TPwgp2DhoiI/AAAAAAAAAPk/HLFHMdC7urY/Mvc3Razor_InsideServerComments_thumb%5B1%5D.png?imgmax=800)
ViewStart
И, напоследок, о том, что уже упоминал ранее. Чтобы выполнить некоторый код для всех View теперь можно использовать файл _ViewStart.cshtml. По аналогии с web.config, можно поместить разные варианты этого файла в разные подпапки с View. Обычно, он используется для задания Layout:![пример содержимого _ViewStart.cshtml пример содержимого _ViewStart.cshtml](http://lh6.ggpht.com/_TMDEK3HEqwk/TPwgqjpD2VI/AAAAAAAAAPs/CvxfvQbyGfQ/_ViewStart_thumb%5B6%5D.png?imgmax=800)
В случае, если Layout задан и во View, то, разумеется, приоритет у заданного во View. Чаще всего, смешение этих двух подходов не является хорошей идеей, однако для демонстрации подойдет.
Резюме
Razor теперь нормально поддерживается в ASP.NET MVC 3, а его возможности для верстки страниц лично меня весьма радуют. Все это немного омрачается неполноценной поддержкой Razor в ReSharper, надеюсь, это ненадолго…В целом, базовые возможности движка Razor на этом этапе я описал (если принять во внимание предыдущий пост про синтаксис Razor), если что-то интересное осталось за кадром или есть какие-то вопросы – милости прошу в комментарии.
Спасибо! Полезно!
ОтветитьУдалитьвсегда было интересно:
ОтветитьУдалитьзачем нужно renderBody ведь можно просто сделать секцию?
>зачем нужно renderBody ведь можно просто сделать секцию?
ОтветитьУдалитьЭто же содержимое самого View, а не его секций. Вроде логично сделать для этого отдельный метод, а не вызывать RenderSection со специальными параметрами или без параметров.
Последнее время двигаемся в сторону лохматых времен (MVC,Razor), когда визуальное представление смешивалось с логикой - код спагетти как в PHP.
ОтветитьУдалитьДизайнеры и верстальщики HTML будут в "восторге" !
To @Анонимный
ОтветитьУдалитьНе соглашусь.
* По сравнению, скажем, с чистым ASP, есть строгая типизация
* MVC - лохматые времена? Вариант с классическими Web Forms (code-behind + попытка сделать web-разработку аналогичной windows-разработке с помощью костылей) видится мне значительно более плохим.
Естественно, это мое личное мнение :)
* IMHO, для сложных систем с хорошей архитектурой код и разметка останутся такими же простыми и понятными.
Спасибо, долго искал про вложеныые layout. Оказалось крайне просто
ОтветитьУдалить