Главная страница   /   5.3. Работа с макетами (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

5.3. Работа с макетами

Другое Razor выражение в файле представления Index.cshtml следующее:

@{
	Layout = null;
}

Это пример блока кода Razor, который позволяет нам включать в представление C# выражения. Блок кода открывается @{ и закрывается }, а выражения, которые он содержит, обрабатываются тогда, когда отрабатывает представление.

Конкретно этот блок кода устанавливает значение свойства Layout на null. Как мы объясним в главе 18, в MVC приложении представления Razor компилируются в C# классы, и используемый базовый класс определяет свойство Layout. Мы покажем вам, как все это работает, в главе 18, но результат установки свойства Layout на null заключается в том, что мы говорим MVC фреймоврку, что наше представление является автономным, и оно будет показывать все содержимое, которое мы должны вернуть клиенту.

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

Создание макета

Для создания макета щелкните правой кнопкой мыши по папке Views в Solution Explorer, нажмите на Add New Item в меню Add и выберите шаблон MVC 4 Layout Page (Razor), как показано на рисунке 5-6.

Рисунок 5-6: Создание нового макета

Назовите файл _BasicLayout.cshtml и нажмите кнопку Add, чтобы создать файл. В листинге 5-5 показано содержимое файла, созданного Visual Studio.

Примечание

Файлы в папке Views, чьи имена начинаются с символа подчеркивания (_) не возвращаются пользователю. Это позволяет нам использовать имена файлов, чтобы различия представления, которые мы хотим показать, и файлы, которые их поддерживают. Имена макетов, которые являются поддерживающими файлами, начинаются с подчеркивания.

Листинг 5-5: Начальное содержание макета
<!DOCTYPE html>
<html>
<head>
	<meta name="viewport" content="width=device-width" />
	<title>@ViewBag.Title</title>
</head>
<body>
	<div>
		@RenderBody()
	</div>
</body>
</html>

Макеты являются специализированной формой представления, и вы видите, что мы выделили в листинге выражения с @. Вызов метода @RenderBody вставляет содержимое представления, указанного методом действия в разметку макета. Другое Razor выражение в макете ищет свойство Title во ViewBag для того, чтобы установить содержание элемента title.

Любые элементы в макете будут применяться к любому представлению, которое использует макет, и именно поэтому макеты по существу являются шаблонами. В листинге 5-6 мы добавили немного простой разметки, чтобы показать, как это работает.

Листинг 5-6: Добавление элементов в макет
<!DOCTYPE html>
<html>
<head>
	<meta name="viewport" content="width=device-width" />
	<title>@ViewBag.Title</title>
</head>
<body>
	<h1>Product Information</h1>
	<div style="padding: 20px; border: solid medium black; font-size: 20pt">
		@RenderBody()
	</div>
	<h2>Visit <a href="http://apress.com">Apress</a></h2>
</body>
</html>

Мы добавили пару элементов заголовков и применили некоторые CSS стили к элементу div, который содержит выражение @RenderBody, просто чтобы было понятно, какой контент приходит из макета, а какой из представления.

Применение макета

Чтобы применить макет к представлению, нам просто нужно установить значение свойства Layout. Мы также можем удалить элементы, которые обеспечивают структуру полной HTML страницы, потому что это будет выпадать из макета. Вы можете увидеть, как мы применили макет, в листинге 5-7, который показывает радикально упрощенный файл Index.cshtml.

Совет

Мы также установили значение для свойства ViewBag.Title, которое будет использоваться в качестве контента элемента title в HTML документе, отправленном обратно пользователю: это не является обязательным, но это хорошая практика. Если значение для свойства не установлено, MVC фреймворк вернет пустой элемент title.

Листинг 5-7: Использование свойства Layout для определения файла представления
@model Razor.Models.Product
@{
	ViewBag.Title = "Product Name";
	Layout = "~/Views/_BasicLayout.cshtml";
}
Product Name: @Model.Name

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

Использование макетов имеет ряд преимуществ. Это позволяет упростить наши представления (что и показано в листинге), это позволяет нам создать общий HTML, который мы можем применить к нескольким представлениям, и, естественно, это сильно упрощает поддержку, потому что мы можем в одном месте изменить общий HTML и быть уверенными, что это изменение будет применяться везде, где используется макет. Чтобы увидеть результат использования макета, запустите приложение из примера. Результат представлен на рисунке 5-7.

Рисунок 5-7: Результат применения простого макета к представлению

Использование файла _ViewStart

Но есть еще кое-что, с чем надо разобраться: то есть, нам нужно указывать файл макета для каждого представления. Это обозначает, что если нам понадобится переименовать файл макета, нам нужно будет найти каждое представление, которое к нему относится, и внести изменения. Это будет процесс, полный ошибок, который идет вразрез с общей темой простоты обслуживания, являющейся фактически лозунгом MVC фреймворка.

Эту проблему можно решить при помощи файла _ViewStart.cshtml. При показе представления MVC фреймворк будет искать файл _ViewStart.cshtml. Содержимое этого файла будет рассматриваться так, как если бы оно содержалось в самом файле представления, и мы можем использовать эту функцию, чтобы автоматически устанавливать значение свойства Layout.

Чтобы создать файл _ViewStart.cshtml, добавьте новый файл макета в папку Views, повторив те действия, которые мы показали вам ранее. Назовите файл _ViewStart.cshtml и измените его так, чтобы он соответствовал листингу 5-8.

Листинг 5-8: Создание файла _ViewStart.cshtml
@{
	Layout = "~/Views/_BasicLayout.cshtml";
}

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

Листинг 5-9: Обновление представления для демонстрации использования файла _ViewStart.cshtml
@model Razor.Models.Product
@{
	ViewBag.Title = "Product Name";
}
Product Name: @Model.Name

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

Внимание

Важно понимать разницу между тем, опускается ли свойство Layout в файле представления или устанавливается на null. Если ваше представление является автономным, и вы не хотите использовать макет, установите значение свойства Layout на null. Если же вы опустите свойство Layout, то MVC фреймворк посчитает, что вы хотите использовать макет и что он должен воспользоваться значением, которое найдет в файле _ViewStart.cshtml.

Демонстрация макетов с общим доступом

Чтобы быстро и просто показать, как предоставить общий доступ для макетов, мы добавили новый метод действия NameAndPrice в контроллер Home. Вы можете посмотреть определение этого метода в листинге 5-10, который демонстрирует изменения, внесенные в файл /Controllers/HomeController.cs.

Листинг 5-10: Добавление нового метода действия в контроллер Home
using Razor.Models;
using System;
using System.Web.Mvc;
namespace Razor.Controllers
{
	public class HomeController : Controller
	{
		Product myProduct = new Product
		{
			ProductID = 1,
			Name = "Kayak",
			Description = "A boat for one person",
			Category = "Watersports",
			Price = 275M
		};
		public ActionResult Index()
		{
			return View(myProduct);
		}
		public ActionResult NameAndPrice()
		{
			return View(myProduct);
		}
	}
}

Этот метод действия просто передает объект MyProduct методу представления, так же как это делает метод действия Index: это не то, что вы могли бы сделать в реальном проекте, но мы демонстрируем функциональность Razor, и такой очень простой пример подходит для наших потребностей.

Щелкните правой кнопкой мыши в редакторе по методу NameAndPrice и выберите из всплывающего меню пункт Add View для отображения диалогового окна Add View. Поставьте галочку на Create a strongly-typed view и выберите из раскрывающегося списка класс Product. Поставьте галочку на Use a layout or master page, как показано на рисунке 5-8.

Рисунок 5-8: Создание представления, которое использует макет

Обратите внимание на текст под опцией Use a layout. Он говорит, что вы должны оставить текстовое поле пустым, если вы указали представление, которое вы хотите использовать в файле _ViewStart.cshtml. Если вы нажмете на этом пункте кнопку Add, будет создано представление без оператора C#, который устанавливает значение для свойства Layout.

Мы собираемся явно указать представление, поэтому щелкните по кнопке с многоточием (...), которая находится справа от текстового поля. Visual Studio покажет вам диалоговое окно, которое позволяет выбрать файл макета, как представлено на рисунке 5-9.

Рисунок 5-9: Выбор файла макета

Соглашение для MVC проектов заключается в размещение файла макета в папке Views, и поэтому диалоговое окно представляет для выбора содержимое именно этой папки. Но это всего лишь соглашение, и поэтому левая панель диалогового окна позволяет перемещаться по проекту, если вдруг вы решили не следовать соглашению.

Мы определили только один файл макета, поэтому выберите _BasicLayout.cshtml и нажмите кнопку ОК, чтобы вернуться в диалоговое окно Add View. Вы увидите, что имя файла макета было помещено в текстовое поле, как показано на рисунке 5-10.

Рисунок 5-10: Определение файла макета при создании представления

Нажмите кнопку Add для создания файла /Views/Home/NameAndPrice.cshtml. Содержимое этого файла представлено в листинге 5-11.

Листинг 5-11: Содержимое представления NameAndPrice
@model Razor.Models.Product
@{
	ViewBag.Title = "NameAndPrice";
	Layout = "~/Views/_BasicLayout.cshtml";
}
<h2>NameAndPrice</h2>

Visual Studio использует немного другой конетент по умолчанию для файлов представления, если вы указываете макет, но вы видите, что результат содержит те же Razor выражения, которые мы использовали, когда сами применяли макет к представлению. Чтобы завершить этот пример, мы добавили в листинг 5-12 простое дополнение к файлу NameAndPrice.cshtml, где отображено значение данных объекта модели представления.

Листинг 5-12: Дополнения в макет NameAndPrice
@model Razor.Models.Product
@{
	ViewBag.Title = "NameAndPrice";
	Layout = "~/Views/_BasicLayout.cshtml";
}
<h2>NameAndPrice</h2>
The product name is @Model.Name and it costs $@Model.Price

Если вы запустите приложение и перейдете к /Home/NameAndPrice, вы увидите результаты, показанные на рисунке 5-11. Как вы и ожидали, общие элементы и стили, определенные в макете, были применены к представлению. Это показывает, как макет может быть использован в качестве шаблона для создания общего внешнего вида приложения (хотя он довольно простой и не совсем привлекательный).

Рисунок 5-11: Содержание файла макета, применяемое к представлению NameAndPrice

Примечание

У нас был бы тот же результат, если бы мы оставили текстовое поле в диалоговом окне Add View пустым и работали с файлом _ViewStart.cshtml. Мы указали файл явно только потому, что мы хотели показать вам функцию Visual Studio, которая помогает выбрать необходимый файл.