Создание единообразного макета на сайтах веб-страницы ASP.NET (Razor)

от Tom фитзмаккен

В этой статье объясняется, как использовать страницы макета на веб-сайте веб-страницы ASP.NET (Razor) для создания многократно используемых блоков содержимого (таких как верхние и нижние колонтитулы) и для создания единообразного вида для всех страниц сайта.

Что вы узнаете:

  • Создание многократно используемых блоков содержимого, таких как верхние и нижние колонтитулы.
  • Как создать единообразный вид для всех страниц сайта с помощью макета.
  • Передача данных во время выполнения на страницу макета.

Это функции ASP.NET, представленные в статье:

  • Блоки содержимого, которые представляют собой файлы, содержащие содержимое в формате HTML, вставляемое на несколько страниц.
  • Страницы макета — страницы, которые содержат содержимое в формате HTML, которое может совместно использоваться страницами на веб-сайте.
  • Методы RenderPage, RenderBodyи RenderSection, которые указывают ASP.NET, куда вставляются элементы страницы.
  • Словарь PageData, который позволяет обмениваться данными между блоками содержимого и страницами макета.

Версии программного обеспечения, используемые в этом руководстве

  • Веб-страницы ASP.NET (Razor) 3

Этот учебник также работает с веб-страницы ASP.NET 2.

О страницах макета

Многие веб-сайты имеют содержимое, отображаемое на каждой странице, например верхний и нижний колонтитулы, или поле, которое сообщает пользователям о том, что они вошли в систему. ASP.NET позволяет создать отдельный файл с блоком содержимого, который может содержать текст, разметку и код, как и обычную веб-страницу. Затем можно вставить блок содержимого на другие страницы сайта, где должны отображаться сведения. Таким образом, не нужно копировать и вставлять одно и то же содержимое на каждую страницу. Создание общего содержимого, подобного, также упрощает обновление сайта. Если необходимо изменить содержимое, можно просто обновить один файл, после чего изменения будут отражены везде, где было вставлено содержимое.

На следующей схеме показано, как работают блоки содержимого. Когда браузер запрашивает страницу с веб-сервера, ASP.NET вставляет блоки содержимого в точку, где вызывается метод RenderPage на главной странице. Затем готовая (Объединенная) страница отправляется в браузер.

Концептуальная схема, показывающая, как метод RenderPage вставляет страницу, на которую указывает ссылка, в текущую страницу.

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

Снимок экрана, показывающий страницу в браузере, которая является результатом выполнения страницы, которая содержит вызовы метода RenderPage.

  1. В корневой папке веб-сайта создайте файл с именем index. cshtml.

  2. Замените существующую разметку следующим:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
      </body>
    </html>
    
  3. В корневой папке создайте папку с именем Shared.

    Note

    Распространенной практикой является хранение файлов, совместно используемых веб-страницами, в папке с именем Shared.

  4. В общей папке создайте файл с именем _Header. cshtml.

  5. Замените имеющееся содержимое следующим:

    <div class="header">This is header text.</div>
    

    Обратите внимание, что имя файла _Header. cshtmlс символом подчеркивания (_) в качестве префикса. ASP.NET не отправляет страницу в браузер, если ее имя начинается с символа подчеркивания. Это не даст пользователям напрямую запрашивать (случайно или иным образом) эти страницы. Рекомендуется использовать символ подчеркивания для наименования страниц, на которых находятся блоки содержимого, так как вы не хотите, чтобы пользователи могли запрашивать эти страницы — , они строго вставляются на другие страницы.

  6. В общей папке создайте файл с именем _Footer. cshtml и замените содержимое следующим:

    <div class="footer">&copy; 2012 Contoso Pharmaceuticals. All rights reserved.
    </div>
    
  7. На странице index. cshtml добавьте два вызова метода RenderPage, как показано ниже:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
        @RenderPage("~/Shared/_Header.cshtml")
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
        @RenderPage("~/Shared/_Footer.cshtml")
    
      </body>
    </html>
    

    В этом примере показано, как вставить блок содержимого на веб-страницу. Вызовите метод RenderPage и передайте ему имя файла, содержимое которого необходимо вставить в этот момент. Здесь вы вставляете содержимое файлов _Headers. cshtml и _Footer. cshtml в файл index. cshtml .

  8. Запустите страницу index. cshtml в браузере. (В WebMatrix в рабочей области файлы щелкните правой кнопкой мыши файл и выберите запустить в браузере.)

  9. В браузере просмотрите источник страницы. (Например, в Internet Explorer щелкните страницу правой кнопкой мыши и выберите пункт Просмотр источника.)

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

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
      <div class="header">
        This is header text.
      </div>
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
      <div class="footer">
        &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
      </div>
    
      </body>
    </html>
    

Создание единообразного вида с помощью страниц макета

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

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

На следующей схеме показано, как страницы содержимого и страницы макета объединяются во время выполнения для создания готовой веб-страницы. Браузер запрашивает страницу содержимого. Страница содержимого содержит в ней код, указывающий страницу макета, используемую для структуры страницы. На странице макета содержимое вставляется в точку, где вызывается метод RenderBody. Блоки содержимого также можно вставить на страницу макета, вызвав метод RenderPage, как в предыдущем разделе. После завершения веб-страницы она отправляется в браузер.

Снимок экрана, показывающий страницу в браузере, которая является результатом выполнения страницы, которая содержит вызовы метода RenderBody.

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

  1. В общей папке веб-сайта создайте файл с именем _layout1. cshtml.

  2. Замените имеющееся содержимое следующим:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Structured Content </title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        @RenderPage("~/Shared/_Header2.cshtml")
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
        </div>
      </body>
    </html>
    

    Для вставки блоков содержимого используется метод RenderPage на странице макета. Страница макета может содержать только один вызов метода RenderBody.

  3. В общей папке создайте файл с именем _Header2. cshtml и замените имеющееся содержимое следующим:

    <div id="header">Creating a Consistent Look</div>
    
  4. В корневой папке создайте новую папку и назовите ее стили.

  5. В папке styles создайте файл с именем site. CSS и добавьте следующие определения стилей:

    h1 {
        border-bottom: 3px solid #cc9900;
        font: 2.75em/1.75em Georgia, serif;
        color: #996600;
    }
    
    ul {
        list-style-type: none;
    }
    
    body {
        margin: 0;
        padding: 1em;
        background-color: #ffffff;
        font: 75%/1.75em "Trebuchet MS", Verdana, sans-serif;
        color: #006600;
    }
    
    #list {
        margin: 1em 0 7em -3em;
        padding: 1em 0 0 0;
        background-color: #ffffff;
        color: #996600;
        width: 25%;
        float: left;
    }
    
    #header, #footer {
        margin: 0;
        padding: 0;
        color: #996600;
    }
    

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

  6. В корневой папке создайте файл с именем Content1. cshtml и замените имеющееся содержимое следующим:

    @{
        Layout = "~/Shared/_Layout1.cshtml";
    }
    
    <h1> Structured Content </h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    

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

  7. Запустите Content1. cshtml в браузере. На подготовленной странице используется формат и таблица стилей, определенные в _layout1. cshtml , и текст (содержимое), определенный в Content1. cshtml.

    [образ]

    Можно повторить шаг 6, чтобы создать дополнительные страницы содержимого, которые затем могут использовать одну и ту же страницу макета.

    Note

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

Разработка страниц макета с несколькими разделами содержимого

Страница содержимого может иметь несколько разделов, что полезно, если вы хотите использовать макеты с несколькими областями с заменяемым содержимым. На странице содержимое каждому разделу присваивается уникальное имя. (Раздел по умолчанию остается неименованным.) На странице макета добавьте метод RenderBody, чтобы указать, где должен отображаться раздел Безымянный (по умолчанию). Затем добавьте отдельные методы RenderSection для отображения именованных разделов по отдельности.

На следующей схеме показано, как ASP.NET обрабатывает содержимое, разделенное на несколько разделов. Каждый именованный раздел содержится в блоке раздела на странице содержимого. (Они называются Header и List в примере). Платформа вставляет раздел содержимого на страницу макета в точке, где вызывается метод RenderSection. Раздел Безымянный (по умолчанию) вставляется в точку, где вызывается метод RenderBody, как было показано ранее.

Концептуальная схема, показывающая, как метод RenderSection вставляет ссылки на разделы в текущую страницу.

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

  1. В общей папке создайте файл с именем _Layout2. cshtml.

  2. Замените имеющееся содержимое следующим:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Multisection Content</title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <div id="header">
          @RenderSection("header")
        </div>
        <div id="list">
          @RenderSection("list")
        </div>
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
        </div>
      </body>
    </html>
    

    Для отображения разделов Header и List используется метод RenderSection.

  3. В корневой папке создайте файл с именем Content2. cshtml и замените имеющееся содержимое следующим:

    @{
        Layout = "~/Shared/_Layout2.cshtml";
    }
    
    @section header {
        <div id="header">
            Creating a Consistent Look
        </div>
    }
    
    @section list {
        <ul>
            <li>Lorem</li>
            <li>Ipsum</li>
            <li>Dolor</li>
            <li>Consecte</li>
            <li>Eiusmod</li>
            <li>Tempor</li>
            <li>Incididu</li>
        </ul>
    }
    
    <h1>Multisection Content</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    

    Эта страница содержимого содержит блок кода в верхней части страницы. Каждый именованный раздел содержится в блоке раздела. Оставшаяся часть страницы содержит раздел содержимого по умолчанию (безымянный).

  4. Запустите Content2. cshtml в браузере.

    Снимок экрана, показывающий страницу в браузере, которая является результатом выполнения страницы, которая содержит вызовы метода RenderSection.

Создание разделов содержимого необязательно

Как правило, разделы, создаваемые на странице содержимого, должны соответствовать разделам, определенным на странице макета. Ошибки могут возникнуть в следующих случаях.

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

Однако это поведение можно переопределить для именованного раздела, объявив раздел как необязательный на странице макета. Это позволяет определить несколько страниц содержимого, которые могут совместно использовать страницу макета, но могут или не иметь содержимого для определенного раздела.

  1. Откройте Content2. cshtml и удалите следующий раздел:

    @section header {
      <div id="header">
        Creating a Consistent Look
      </div>
    }
    
  2. Сохраните страницу и запустите ее в браузере. Отображается сообщение об ошибке, так как страница содержимого не предоставляет содержимое для раздела, определенного на странице макета, а именно в разделе заголовка.

    Снимок экрана, показывающий ошибку, которая возникает при запуске страницы, вызывающей метод RenderSection, но соответствующий раздел не предоставляется.

  3. В общей папке откройте страницу _Layout2. cshtml и замените эту строку:

    @RenderSection("header")
    

    на новый код:

    @RenderSection("header", required: false)
    

    В качестве альтернативы можно заменить предыдущую строку кода следующим блоком кода, что дает те же результаты:

    @if (IsSectionDefined("header")) {
        @RenderSection("header")
    }
    
  4. Снова запустите страницу Content2. cshtml в браузере. (Если эта страница по-прежнему открыта в браузере, можно просто обновить ее.) На этот раз страница отображается без ошибок, несмотря на то, что в ней нет заголовка.

Передача данных на страницы макета

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

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

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

Концептуальная схема, показывающая, как страница содержимого может заполнить словарь Пажедата и передать эту информацию на страницу макета.

В следующей процедуре показано, как передавать данные со страницы содержимого на страницу макета. При запуске страницы отображается кнопка, позволяющая пользователю скрывать или отображать список, определенный на странице макета. Когда пользователь нажимайте кнопку, он устанавливает значение true/false (логическое) в свойстве PageData. Страница макета считывает это значение и, если оно имеет значение false, скрывает список. Значение также используется на странице содержимое, чтобы определить, следует ли отображать кнопку Скрыть список или Показать список .

[образ]

  1. В корневой папке создайте файл с именем Content3. cshtml и замените имеющееся содержимое следующим:

    @{
        Layout = "~/Shared/_Layout3.cshtml";
    
        PageData["Title"] = "Passing Data";
        PageData["ShowList"] = true;
    
        if (IsPost) {
            if (Request.Form["list"] == "off") {
                PageData["ShowList"] = false;
            }
        }
    }
    
    @section header {
      <div id="header">
        Creating a Consistent Look
      </div>
    }
    
    <h1>@PageData["Title"]</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    
    @if (PageData["ShowList"] == true) {
        <form method="post" action="">
          <input type="hidden" name="list" value="off" />
          <input type="submit" value="Hide List" />
        </form>
    }
    else {
        <form method="post" action="">
          <input type="hidden" name="list" value="on" />
          <input type="submit" value="Show List" />
        </form>
    }
    

    В коде хранятся два фрагмента данных в свойстве — PageData заголовок веб-страницы, значение true или false, чтобы указать, следует ли отображать список.

    Обратите внимание, что ASP.NET позволяет поочередно размещать HTML-разметку на странице с помощью блока кода. Например, блок if/else в тексте страницы определяет, какая форма должна отображаться в зависимости от того, имеет ли PageData["ShowList"] значение true.

  2. В общей папке создайте файл с именем _Layout3. cshtml и замените имеющееся содержимое следующим:

    <!DOCTYPE html>
    <html>
      <head>
        <title>@PageData["Title"]</title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <div id="header">
          @RenderSection("header")
        </div>
          @if (PageData["ShowList"] == true) {
              <div id="list">
                @RenderPage("~/Shared/_List.cshtml")
              </div>
          }
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          <p>&copy; 2012 Contoso Pharmaceuticals. All rights reserved.</p>
        </div>
      </body>
    </html>
    

    Страница макета содержит выражение в элементе <title>, который получает значение заголовка из свойства PageData. Он также использует значение ShowList свойства PageData, чтобы определить, следует ли отображать блок содержимого списка.

  3. В общей папке создайте файл с именем _List. cshtml и замените имеющееся содержимое следующим:

    <ul>
      <li>Lorem</li>
      <li>Ipsum</li>
      <li>Dolor</li>
      <li>Consecte</li>
      <li>Eiusmod</li>
      <li>Tempor</li>
      <li>Incididu</li>
    </ul>
    
  4. Запустите страницу Content3. cshtml в браузере. Отобразится страница со списком, видимым в левой части страницы, и кнопку Скрыть список внизу.

    Снимок экрана, показывающий страницу, содержащую список, и кнопку с текстом "скрыть список".

  5. Щелкните Скрыть список. Список исчезнет, а кнопка изменится на отобразить список.

    Снимок экрана, на котором показана страница, не содержащая список, и кнопка с текстом "Показать список".

  6. Нажмите кнопку Показать список и снова отобразится список.

Дополнительные ресурсы

Настройка поведения на уровне сайта для веб-страницы ASP.NET