Знакомство веб-страницы ASP.NET. Создание согласованного макета
; автор — Том ФитцМакен (Tom FitzMacken)
В этом руководстве показано, как с помощью макетов создать согласованный внешний вид страниц на сайте, использующем веб-страницы ASP.NET. Предполагается, что вы завершили серию до удаления данных базы данных в веб-страницы ASP.NET.
Из этого руководства вы узнаете, как выполнять такие задачи:
- Что такое страница макета.
- Как объединять страницы макета с динамическим содержимым.
- Передача значений на страницу макета.
Сведения о макетах
Все страницы, созданные вами до сих пор, были полными, автономными страницами. Все они принадлежат к одному сайту, но у них нет общих элементов или стандартного вида.
Большинство сайтов имеют согласованный внешний вид и макет. Например, если вы перейдете на сайт Microsoft.com/web и посмотрите вокруг, вы увидите, что все страницы соответствуют общему макету и визуальной теме:
Неэффективным способом создания этого макета является определение заголовка, панели навигации и нижнего колонтитула отдельно на каждой из ваших страниц. Вы будете дублировать одну и ту же разметку каждый раз. Если вы хотите что-то изменить (например, обновить нижний колонтитул), необходимо изменить каждую страницу отдельно.
Вот где страницы макета поступают. В веб-страницы ASP.NET можно определить страницу макета, которая предоставляет общий контейнер для страниц на сайте. Например, страница макета может содержать верхний колонтитул, область навигации и нижний колонтитул. Страница макета содержит заполнитель, куда помещается содержимое main.
Затем можно определить отдельные страницы содержимого, содержащие разметку и код только для этой страницы. Страницы содержимого не обязательно должны быть полными HTML-страницами; они даже не должны иметь <body>
элемент. Они также содержат строку кода, которая сообщает ASP.NET, на какой странице макета вы хотите отобразить содержимое. Вот рисунок, показывающий примерно, как работает эта связь:
Это взаимодействие легко понять, когда вы видите его в действии. В этом руководстве вы измените страницы фильмов для использования макета.
Добавление страницы макета
Сначала вы создадите страницу макета, которая определяет типичный макет страницы с верхним, нижним колонтитулов и областью для main содержимого. На сайте WebPagesMovies добавьте страницу CSHTML с именем _Layout.cshtml.
Символ подчеркивания в начале ( _
) имеет важное значение. Если имя страницы начинается с символа подчеркивания, ASP.NET не будет напрямую отправлять страницу в браузер. Это соглашение позволяет определить страницы, которые необходимы для вашего сайта, но пользователи не должны иметь возможность запрашивать напрямую.
Замените содержимое на странице следующим:
<!DOCTYPE html>
<html>
<head>
<title>My Movie Site</title>
<link href="~/Styles/Movies.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container">
<div id="header">
<h1>My Movie Site</h1>
</div>
<div id="main">
@RenderBody()
</div>
<div id="footer">
© @DateTime.Now.Year My Movie Site
</div>
</div>
</body>
</html>
Как видите, эта разметка представляет собой просто HTML, в котором используются <div>
элементы для определения трех разделов на странице и еще <div>
один элемент для хранения этих трех разделов. Нижний колонтитул содержит фрагмент кода Razor: @DateTime.Now.Year
, который будет отображать текущий год в этом расположении на странице.
Обратите внимание, что есть ссылка на таблицу стилей с именем Movies.css. В таблице стилей определяются сведения о физическом макете элементов. Вы создадите это через мгновение.
Единственной необычной функцией на этой странице _Layout.cshtml является @Render.Body()
строка. Это заполнитель, куда будет идти содержимое при слиянии этого макета с другой страницей.
Добавление CSS-файла
Предпочтительный способ определить фактическое расположение (то есть внешний вид) элементов на странице — использовать правила каскадной таблицы стилей (CSS). Поэтому вы создадите CSS-файл с правилами для нового макета.
В webMatrix выберите корень сайта. Затем на вкладке ленты Файлы щелкните стрелку под кнопкой Создать и выберите команду Создать папку.
Назовите новую папку Стили.
В новой папке Стили создайте файл с именем Movies.css.
Замените содержимое нового CSS-файла следующим кодом:
html{ height:100%; margin:0; padding:0; }
body {
height:60%;
font-family:'Trebuchet MS', 'Arial', 'Helvetica', 'sans-serif';
font-size:10pt;
background-color: LightGray;
line-height:1.6em;
}
h1{ font-size:1.6em; }
h2{ font-size:1.4em; }
#container{
min-height:100%;
position:relative;
left:10%;
}
#header{
padding:8px;
width:80%;
background-color:#4b6c9e;
color:White;
}
#main{
width:80%;
padding: 8px;
padding-bottom:4em;
background-color:White;
}
#footer{
width:80%;
height:2em;
padding:8px;
margin-top:-2em;
background-color:LightGray;
}
.head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
.grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
.alt { background-color: #E8E8E8; color: #000; }
.selected {background-color:Yellow;}
span.caption {width:100px;}
span.dataDisplay {font-weight:bold;}
Мы не будем много говорить об этих правилах CSS, за исключением двух вещей. Один из них заключается в том, что помимо настройки шрифтов и размеров, правила используют абсолютное позиционирование для определения расположения колонтитулов и main области содержимого. Если вы не знакомы с позиционированием в CSS, ознакомьтесь с руководством по размещению CSS на сайте W3Schools.
Обратите внимание, что в нижней части мы скопировали правила стиля, которые изначально были определены отдельно в файле Movies.cshtml . Эти правила использовались в руководстве Общие сведения о отображении данных с помощью веб-страницы ASP.NET для создания вспомогательной WebGrid
разметки отрисовки, добавляющей полосы в таблицу. (Если вы собираетесь использовать CSS-файл для определений стилей, вы также можете поместить в него правила стиля для всего сайта.)
Обновление файла Movies для использования макета
Теперь вы можете обновить существующие файлы на сайте, чтобы использовать новый макет. Откройте файл Movies.cshtml . В верхней части в качестве первой строки кода добавьте следующее:
Layout = "~/_Layout.cshtml";
Теперь страница начинается следующим образом:
@{
Layout = "~/_Layout.cshtml";
var db = Database.Open("WebPagesMovies") ;
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";
// Etc.
Эта строка кода сообщает ASP.NET, что при запуске страницы Фильмы она должна быть объединена с файлом _Layout.cshtml .
Так как файл Movies.cshtml теперь использует страницу макета, вы можете удалить разметку со страницы Movies.cshtml , которую выполняет файл _Layout.cshtml . <!DOCTYPE>
Извлеките открывающий и <body>
закрывающий теги , <html>
и . Извлеките весь <head>
элемент и его содержимое, включая правила стиля для сетки, так как теперь эти правила есть в CSS-файле . Пока вы находитесь в нем, измените существующий <h1>
элемент на элемент <h2>
; у вас уже есть <h1>
элемент на странице макета. Измените текст на <h2>
"Список фильмов".
Обычно вам не нужно вносить такие изменения на странице содержимого. При запуске сайта со страницы макета вы создаете страницы содержимого без всех этих элементов. В этом случае, однако, вы преобразуете автономную страницу в страницу, которая использует макет, поэтому есть немного очистки.
По завершении страница Movies.cshtml будет выглядеть следующим образом:
@{
Layout = "~/_Layout.cshtml";
var db = Database.Open("WebPagesMovies") ;
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";
if(!Request.QueryString["searchGenre"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
searchTerm = Request.QueryString["searchGenre"];
}
if(!Request.QueryString["searchTitle"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
}
var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}
<h2>List Movies</h2>
<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre"
value="@Request.QueryString["searchGenre"]" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>
<div>
<label for="SearchTitle">Movie title contains the following:</label>
<input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
<input type="Submit" value="Search Title" /><br/>
</div>
</form>
<div>
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year"),
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
)
)
</div>
<p><a href="~/AddMovie">Add a movie</a></p>
Тестирование макета
Теперь вы можете увидеть, как выглядит макет. В WebMatrix щелкните правой кнопкой мыши страницу Movies.cshtml и выберите Запустить в браузере. При отображении страницы в браузере она выглядит следующим образом:
ASP.NET объединили содержимое страницы Movies.cshtml со страницей _Layout.cshtml прямо там RenderBody
, где находится метод . И, конечно, страница _Layout.cshtml ссылается на CSS-файл , который определяет внешний вид страницы.
Обновление страницы AddMovie для использования макета
Реальное преимущество макетов заключается в том, что вы можете использовать их для всех страниц на сайте. Откройте страницу AddMovie.cshtml .
Вы помните, что на странице AddMovie.cshtml изначально были некоторые правила CSS, определяющие внешний вид сообщений об ошибках проверки. Так как у вас есть CSS-файл для сайта, вы можете переместить эти правила в CSS-файл . Удалите их из файла AddMovie.cshtml и добавьте в нижнюю часть файла Movies.css . Вы перемещаете следующие правила:
.field-validation-error {
font-weight:bold;
color:red;
background-color:yellow;
}
.validation-summary-errors{
border:2px dashed red;
color:red;
background-color:yellow;
font-weight:bold;
margin:12px;
}
Теперь внесите те же изменения в AddMovie.cshtml , что и для Movies.cshtml — добавьте Layout="~/_Layout.cshtml;
и удалите разметку HTML, которая теперь является лишней. Измените <h1>
элемент на <h2>
. Когда все будет готово, страница будет выглядеть следующим образом:
@{
Layout = "~/_Layout.cshtml";
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
var title = "";
var genre = "";
var year = "";
if(IsPost){
if(Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand =
"INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
}
<h2>Add a Movie</h2>
@Html.ValidationSummary()
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@Request.Form["title"]" />
@Html.ValidationMessage("title")
</p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
@Html.ValidationMessage("genre")
</p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
@Html.ValidationMessage("year")
</p>
<p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
</fieldset>
</form>
Запустите страницу. Теперь это выглядит следующим образом:
Вы хотите внести аналогичные изменения на страницы сайта — EditMovie.cshtml и DeleteMovie.cshtml. Однако перед этим можно внести еще одно изменение в макет, которое сделает его немного более гибким.
Передача сведений о заголовке на страницу макета
Созданная вами страница _Layout.cshtml содержит <title>
элемент , для которого задано значение "Мой сайт фильма". В большинстве браузеров содержимое этого элемента отображается в виде текста на вкладке:
Эти сведения о заголовке являются общими. Предположим, что вы хотите, чтобы текст заголовка был более конкретным для текущей страницы. (Текст заголовка также используется поисковыми системами для определения вашей страницы.) Вы можете передать сведения со страницы содержимого , например Movies.cshtml или AddMovie.cshtml , на страницу макета, а затем использовать эти сведения для настройки отображения страницы макета.
Снова откройте страницу Movies.cshtml . В коде вверху добавьте следующую строку:
Page.Title = "List Movies";
Объект Page
доступен на всех страницах .cshtml и предназначен для этого, а именно для обмена информацией между страницей и ее макетом.
Откройте страницу _Layout.cshtml . Измените <title>
элемент так, чтобы он выглядел следующим образом:
<title>@Page.Title</title>
Этот код отображает все, что находится в свойстве Page.Title
прямо в этом расположении на странице.
Запустите страницу Movies.cshtml . На этот раз на вкладке браузера отображается то, что вы передали Page.Title
в качестве значения :
При необходимости просмотрите источник страницы в браузере. Видно, что <title>
элемент отображается как <title>List Movies</title>
.
Совет
Объект Page
Полезной особенностью Page
является то, что это динамический объект— Title
свойство не является фиксированным или зарезервированным именем. Для значения Page
объекта можно использовать любое имя. Например, можно легко передать заголовок с помощью свойства с именем Page.CurrentName
или Page.MyPage
. Единственное ограничение заключается в том, что имя должно соответствовать обычным правилам для именованных свойств. (Например, имя не может содержать пробел.)
С помощью объекта можно передать любое количество значений Page
. Если вы хотите передать сведения о фильме на страницу макета, можно передать значения с помощью таких элементов, как Page.MovieTitle
и Page.Genre
и Page.MovieYear
. (Или любые другие имена, которые вы придумали для хранения информации.) Единственное требование, которое, вероятно, очевидно, заключается в том, что вы должны использовать одни и те же имена на странице содержимого и на странице макета.
Информация, передаваемая с помощью Page
объекта , не ограничивается только текстом, отображаемым на странице макета. Вы можете передать значение на страницу макета, а затем код на странице макета может использовать значение, чтобы решить, следует ли отображать раздел страницы, какой CSS-файл использовать и т. д. Значения, которые вы передаете в объект , похожи на Page
любые другие значения, используемые в коде. Просто значения создаются на странице содержимого и передаются на страницу макета.
Откройте страницу AddMovie.cshtml и добавьте строку в начало кода, которая содержит заголовок страницы AddMovie.cshtml :
Page.Title = "Add a Movie";
Запустите страницу AddMovie.cshtml . Вы увидите новый заголовок:
Обновление оставшихся страниц для использования макета
Теперь вы можете завершить оставшиеся страницы на сайте, чтобы они использовали новый макет. По очереди откройте файл EditMovie.cshtml и DeleteMovie.cshtml и внесите одинаковые изменения.
Добавьте строку кода, которая ссылается на страницу макета:
Layout = "~/_Layout.cshtml";
Добавьте строку, чтобы задать заголовок страницы:
Page.Title = "Edit a Movie";
или:
Page.Title = "Delete a Movie";
Удалите всю постороннюю html-разметку. По сути, оставьте только биты, которые находятся внутри <body>
элемента (а также блок кода в верхней части).
Измените <h1>
элемент на элемент .<h2>
После внесения этих изменений проверьте каждый из них и убедитесь, что он отображается правильно и что название правильно.
Прощание о страницах макета
В этом руководстве вы создали страницу _Layout.cshtml и использовали RenderBody
метод для слияния содержимого с другой страницы. Это базовый шаблон для использования макетов в веб-страницах.
Страницы макета имеют дополнительные функции, которые здесь не рассматриваются. Например, можно вкладывать страницы макета— одна страница макета может ссылаться на другую. Вложенные макеты могут быть полезны, если вы работаете с подразделами сайта, для которых требуются разные макеты. Вы также можете использовать дополнительные методы (например, RenderSection
) для настройки именованных разделов на странице макета.
Сочетание страниц макета и CSS-файлов является эффективным. Как вы увидите в следующей серии учебников, в WebMatrix вы можете создать сайт на основе шаблона, который предоставляет сайт с предварительно созданными функциями. Шаблоны хорошо используют страницы макета и CSS для создания сайтов, которые отлично выглядят и имеют такие функции, как меню. Ниже приведен снимок экрана домашней страницы сайта на основе шаблона, в котором показаны функции, использующие страницы макета и CSS:
Полное описание страницы фильма (обновлено для использования страницы макета)
@{
Layout = "~/_Layout.cshtml";
Page.Title = "List Movies";
var db = Database.Open("WebPagesMovies") ;
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";
if(!Request.QueryString["searchGenre"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
searchTerm = Request.QueryString["searchGenre"];
}
if(!Request.QueryString["searchTitle"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
}
var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}
<h2>List Movies</h2>
<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>
<div>
<label for="SearchTitle">Movie title contains the following:</label>
<input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
<input type="Submit" value="Search Title" /><br/>
</div>
</form>
<div>
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year"),
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
)
)
</div>
<p><a href="~/AddMovie">Add a movie</a></p>
Полный список страниц для страницы добавления фильма (обновлено для макета)
@{
Layout = "~/_Layout.cshtml";
Page.Title = "Add a Movie";
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
var title = "";
var genre = "";
var year = "";
if(IsPost){
if(Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) VALUES(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
}
<h2>Add a Movie</h2>
@Html.ValidationSummary()
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@Request.Form["title"]" />
@Html.ValidationMessage("title")
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
@Html.ValidationMessage("genre")
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
@Html.ValidationMessage("year")
<p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
</fieldset>
</form>
Полный список страниц для удаления страницы фильма (обновлен для макета)
@{
Layout = "~/_Layout.cshtml";
Page.Title = "Delete a Movie";
var title = "";
var genre = "";
var year = "";
var movieId = "";
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].AsInt() > 0){
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was found for that ID.");
// If you are using a version of ASP.NET Web Pages 2 that's
// earlier than the RC release, comment out the preceding
// statement and uncomment the following one.
//ModelState.AddFormError("No movie was found for that ID.");
}
}
else{
Validation.AddFormError("No movie was found for that ID.");
// If you are using a version of ASP.NET Web Pages 2 that's
// earlier than the RC release, comment out the preceding
// statement and uncomment the following one.
//ModelState.AddFormError("No movie was found for that ID.");
}
}
if(IsPost && !Request["buttonDelete"].IsEmpty()){
movieId = Request.Form["movieId"];
var db = Database.Open("WebPagesMovies");
var deleteCommand = "DELETE FROM Movies WHERE ID = @0";
db.Execute(deleteCommand, movieId);
Response.Redirect("~/Movies");
}
}
<h2>Delete a Movie</h2>
@Html.ValidationSummary()
<p><a href="~/Movies">Return to movie listing</a></p>
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><span>Title:</span>
<span>@title</span></p>
<p><span>Genre:</span>
<span>@genre</span></p>
<p><span>Year:</span>
<span>@year</span></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonDelete" value="Delete Movie" /></p>
</fieldset>
</form>
Полный список страниц для редактирования страницы фильма (обновлен для макета)
@{
Layout = "~/_Layout.cshtml";
Page.Title = "Edit a Movie";
var title = "";
var genre = "";
var year = "";
var movieId = "";
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was selected.");
// If you are using a version of ASP.NET Web Pages 2 that's
// earlier than the RC release, comment out the preceding
// statement and uncomment the following one.
//ModelState.AddFormError("No movie was selected.");
}
}
else{
Validation.AddFormError("No movie was selected.");
// If you are using a version of ASP.NET Web Pages 2 that's
// earlier than the RC release, comment out the preceding
// statement and uncomment the following one.
//ModelState.AddFormError("No movie was selected.");
}
}
if(IsPost){
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
Validation.RequireField("movieid", "No movie ID was submitted!");
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
movieId = Request.Form["movieId"];
if(Validation.IsValid()){
var db = Database.Open("WebPagesMovies");
var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
db.Execute(updateCommand, title, genre, year, movieId);
Response.Redirect("~/Movies");
}
}
}
<h2>Edit a Movie</h2>
@Html.ValidationSummary()
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@title" /></p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@genre" /></p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@year" /></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
</fieldset>
</form>
<p><a href="~/Movies">Return to movie listing</a></p>
Ближайшие к следующему
В следующем руководстве вы узнаете, как опубликовать сайт в Интернете, чтобы его могли видеть все пользователи.
Дополнительные ресурсы
- Создание согласованного оформления — статья, в которую приводятся дополнительные сведения о работе с макетами. Здесь также описывается, как передать значение на страницу макета, отображающую или скрывающую часть содержимого.
- Вложенные страницы макета с razor — Майк Бринд в блоге пример того, как вкладывать страницы макета. (Включает скачивание страниц.)