Мастер-страницы layout

Последнее обновление: 23.03.2022

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

Например, возьмем простейший проект ASP.NET Core по типу ASP.NET Core Empty.

Подключение MVC в пустой проект ASP.NET Core

Сначала в файле Program.cs подключим функционал контроллеров и представлений:

var builder = WebApplication.CreateBuilder(args);

// добавляем поддержку контроллеров с представлениями
builder.Services.AddControllersWithViews();
var app = builder.Build();

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Пусть в проекте будет папка Controllers, где будет располагаться контроллер HomeController с двумя методами:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index() => View();
        public IActionResult About() => View();
    }
}

Оба действия контроллера возвращают ViewResult. Поэтому нам надо добавить для них представления. Но в начале определим мастер-страницу layout.

Создадим в проекте папку Views, а в ней создадим папку Shared. Далее добавим в каталог Views/Shared новое представление, которое назовем _Layout.cshtml. Для добавления мастер-страниц в Visual Studio можно использовать шаблон файла Razor Layout:

Razor Layout в ASP.NET Core MVC и C#

После добавления файла _Layout.cshtml изменим его код следующим образом:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>METANIT.COM | @ViewBag.Title</title>
</head>
<body>
    <h2>@ViewBag.Title</h2>
    <div><a href="/Home/Index">Home</a> | <a href="/Home/About">About</a></div>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Код мастер-страницы напоминает полноценную веб-страницу: здесь присутствуют основные теги <html>, <head>, <body> и так далее. И также здесь могут использоваться конструкции Razor. Фактически это то же самое представление. Например, через выраженеи @ViewBag.Title из каждого отдельного представления будет передаваться значение для заголовка веб-страницы.

Главное же отличие от обычных представлений состоит в использовании метода @RenderBody(), который является плейсхолдером и на место которого потом будут подставляться другие представления, использующие данную мастер-страницу. В итоге мы сможем легко установить для всех представлений веб-приложения единообразный стиль оформления.

Теперь добавим в папку Views новую папку Home для хранения представлений контроллера HomeController. Далее в эту папку поместим новое представление Index.cshtml (для метода Index):

@{
    ViewBag.Title = "Index";
    Layout = "/Views/Shared/_Layout.cshtml";
}
<h3>Index Content</h3>

Здесь задается значение ViewBag.Title, которое применяется на мастер-странице для выводпа заголовка.

Кроме того, с помощью свойства Layout устанавливается используемая мастер-страница layout. В данном случае это файл по пути /Views/Shared/_Layout.cshtml

Также добавим в папку Views/Home новое представление About.cshtml (для метода About):

@{
    ViewBag.Title = "About";
    Layout = "/Views/Shared/_Layout.cshtml";
}
<h3>About Content</h3>

Оно выглядит аналогично представлению Index.cshtml.

В итоге весь проект будет выглядеть следующим образом:

представления views и layout в ASP.NET Core MVC и C#

Запустим проект и в браузере при обращении к обоим действиям контроллера - Index и About мы лицезреем в браузере единообразую веб-страницу:

подключение layout в представления ASP.NET Core MVC и C#

При необходимости мы можем определять разные мастер-страницы, например, отдельные мастер-страницы для разных контроллеров, и таким образом подключать в конкретные представления.

ViewStart

Хотя выше приведенный код вполне успешно работает, у нас есть одна проблема - мы сталкиваемся с необходимостью в каждом представлении явным образом прописывать, какую мастер-страницу layout будет применять представление. Чтобы упростить данное действие, можно применять файлы _ViewStart.cshtml

Итак, добавим в папку Views новое представление, которое назовем _ViewStart.cshtml.

_ViewStart.cshtml в ASP.NET Core MVC и C#

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

Определим в файле _ViewStart.cshtml следующий код:

@{
    Layout = "_Layout";
}

В каждом представлении через синтаксис Razor доступно свойство Layout, которое хранит ссылку на мастер-страницу. Здесь в качестве мастер страницы устанавливается файл _Layout.cshtml. При этом расширение можно не использовать.

Когда будет происходить рендеринг представления, то система будет искать мастер страницу _Layout по следующим путям:

/Views/[Название_контроллера]/_Layout.cshtml
/Views/Shared/_Layout.cshtml

Если в обеих папках: и в /Views/[Название_контроллера], и в /Views/Shared/ имеется файл с одинаковым именем, например, _Layout.cshtml, то к представлению применяется файл, который находится с ним в одной папке как более приоритетный. То есть таким образом мы можем определить для представлений каждого отдельного контроллера или представлений, которые находятся в одной папке, свою отдельную мастер-страницу.

После определения этого файла мы можем удалить из представлений Index.cshtml и About.cshtml подключение мастер-страницы. Например, представление Index.cshtml:

@{
    ViewBag.Title = "Index";
}
<h3>Index Content</h3>

Переопределение мастер-страницы

Если вдруг мы хотим глобально по всему проекту поменять мастер-страницу на другой файл, который расположен в какой-то другой папке, например, в корне каталога Views, то нам надо использовать полный путь к файлу в _ViewStart.cshtml:

@{
    Layout = "~/Views/_Layout.cshtml";
}

Код из _ViewStart.cshtml выполняется до любого кода в представлении. И чтобы переопределить мастер-страницу, в представлении доcтаточно установить свойство Layout.

Естественно также мы можем переопределить мастер-страницу в каждом отдельном представлении с помощью свойства Layout.

@{
    ViewBag.Title = "Home Page";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Представление Index.cshtml</h2>

Мы можем вообще не использовать мастер-страницу, тогда в представлении свойству Layout надо присвоить значение null:

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Home Page</title>
</head>
<body>
    <h2>Представление Index.cshtml</h2>
</body>
</html>

Секции

Кроме метода RenderBody(), который вставляет освновное содержимое представлений, мастер-страниц может также использовать специальный метод RenderSection() для вставки секций. Мастер-страница может иметь несколько секций, куда представления могут поместить свое содержимое. Например, добавим к мастер-странице _Layout.cshtml секцию с именем "footer":

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>METANIT.COM | @ViewBag.Title</title>
</head>
<body>
    <h2>@ViewBag.Title</h2>
    <div><a href="/Home/Index">Home</a> | <a href="/Home/About">About</a></div>
    <div>
        @RenderBody()
    </div>
    <footer>@RenderSection("Footer")</footer>
</body>
</html>

Теперь при запуске предыдущего представления Index мы получим ошибку, так как секция Footer не определена. По умолчанию представление должно передавать содержание для каждой секции мастер-страницы. Поэтому добавим вниз представления Index секцию footer. Это мы можем сделать с помощью выражения @section:

@{
    ViewBag.Title = "Index";
}
</h3>Index Content</h3>

@section Footer {
   Copyright© Metanit.com, @DateTime.Now.Year. All rights reserved
}
render section in layout в представлениях ASP.NET Core MVC и C#

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

Первый вариант заключается в использовании перегруженной версии метода RenderSection, которая позволяет указать, что данную секцию не обязательно определять в представлении. Чтобы отметить секцию Footer в качестве необязательной, надо передать в метод в качестве второго параметра значение false:

<footer>@RenderSection("Footer", false)</footer>

Второй вариант позволяет задать содержание секции по умолчанию, если данная секция не определена в представлении:

<footer>
    @if (IsSectionDefined("Footer"))
    {
        @RenderSection("Footer")
    }
    else
    {
        <span>Содержание элемента footer по умолчанию.</span>
    }
</footer>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850