Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве показано, как использовать макеты для создания согласованного поиска страниц на сайте, использующем веб-страницы ASP.NET. Предполагается, что вы завершили изучение серии через удаление данных базы данных на веб-страницах ASP.NET.
Что вы узнаете:
- Что такое страница макета.
- Как сочетать страницы макета с динамическим содержимым.
- Как осуществляется передача значений на страницу макета.
Сведения о макетах
Все страницы, которые вы создали до сих пор, были завершены, автономные страницы. Все они принадлежат одному сайту, но у них нет общих элементов или стандартного вида.
Большинство сайтов имеют согласованный вид и макет. Например, если перейти на сайт Microsoft.com/web и посмотреть вокруг, вы увидите, что все страницы соответствуют общему макету и визуальной теме:
Неэффективным способом создания этого макета будет определение заголовка, панели навигации и нижнего колонтитула отдельно на каждой странице. Вы будете дублировать одну и ту же разметку каждый раз. Если вы хотите изменить что-то (например, обновить нижний колонтитул), необходимо изменить каждую страницу отдельно.
Вот где приходят страницы макета . В ASP.NET веб-страницы можно определить страницу макета, которая предоставляет общий контейнер для страниц на сайте. Например, страница макета может содержать верхний колонтитул, область навигации и нижний колонтитул. Страница макета содержит заполнитель, в который размещается основное содержимое.
Затем можно определить отдельные страницы содержимого, содержащие разметку и код только для этой страницы. Страницы содержимого не обязаны представлять собой полные HTML-страницы, они даже не должны иметь элемент <body>. У них также есть строка кода, которая сообщает ASP.NET, в какой странице макета будет отображено содержимое. Вот рисунок, показывающий примерно, как работает эта связь:
Это взаимодействие легко понять, когда его видишь в работе. В этом руководстве вы измените страницы фильмов на использование макета.
Добавление страницы макета
Сначала вы создадите страницу макета, которая определяет типичный макет страницы с верхним, нижним колонтитуловом и областью для основного содержимого. На сайте 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 выберите корневой каталог сайта. Затем на вкладке "Файлы" ленты щелкните стрелку под кнопкой "Создать " и нажмите кнопку "Создать папку".
Назовите новую папку Styles.
В новой папке "Стили" создайте файл с именем 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, за исключением того, чтобы отметить две вещи. В дополнение к настройке шрифтов и размеров, правила используют абсолютное позиционирование для определения расположения шапки, колонтитула и основной области содержимого. Если вы не знакомы с размещением в CSS, ознакомьтесь с учебником по размещению CSS на веб-сайте W3Schools.
Другое, что следует отметить, что в нижней части мы копировали правила стиля, которые изначально были определены отдельно в файле Movies.cshtml . Эти правила использовались в руководстве по введению в отображение данных с помощью веб-страниц ASP.NET, чтобы вспомогательный элемент разметки добавил полосы в таблицу. (Если вы собираетесь использовать файл .css для определений стилей, вы также можете поместить правила стиля для всего сайта в него.)
Обновление файла фильмов для применения макета
Теперь вы можете обновить существующие файлы на сайте, чтобы использовать новый макет. Откройте файл 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>, <html>, и <body>. Извлеките весь <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> элемент, который имеет значение "My Movie Site". Большинство браузеров отображают содержимое этого элемента в виде текста на вкладке:
Эти сведения о заголовке являются универсальными. Предположим, что текст заголовка будет более конкретным для текущей страницы. (Текст заголовка также используется поисковыми системами для определения того, что о вашей странице.) Вы можете передать информацию из страницы содержимого, например 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 заключается в том, что это динамический объект — 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 — Майк Бринд в блоге о примере того, как вложить страницы макета. (Включает скачивание страниц.)