Часть 3. представления и ViewModels

Джон Гэллоуэй

Музыкальное хранилище MVC — это учебное приложение, в котором представлены и объясняются пошаговые инструкции по использованию ASP.NET MVC и Visual Studio для разработки веб-приложений.

Музыкальное хранилище MVC — это упрощенная реализация в магазине, которая продает музыкальные альбомы в сети и реализует базовое администрирование сайта, вход пользователя в систему и функции корзины покупок.

В этой серии руководств подробно описаны все шаги, предпринятые для создания примера приложения музыкального хранилища ASP.NET MVC. В части 3 представлены представления и ViewModels.

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

Добавление шаблона представления

Чтобы использовать шаблон представления, мы изменим метод индекса HomeController, чтобы он возвращал ActionResult, и имел возвращаемое представление (), как показано ниже:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

Приведенное выше изменение указывает, что вместо возврата строки мы хотим использовать "View" для создания результата.

Теперь мы добавим в наш проект соответствующий шаблон представления. Для этого поместите текстовый курсор в метод действия индекса, щелкните его правой кнопкой мыши и выберите "добавить представление". Откроется диалоговое окно Добавление представления:

Диалоговое окно "Добавление представления" позволяет быстро и легко создавать файлы шаблонов представления. По умолчанию диалоговое окно "добавить представление" предварительно заполняет имя создаваемого шаблона представления, чтобы оно соответствовало тому методу действия, который будет его использовать. Так как мы использовали контекстное меню "добавить представление" в методе действия Index () нашего HomeController, в диалоговом окне "добавить представление" выше указано "index", как имя представления, предварительно заполненное по умолчанию. Изменять параметры этого диалогового окна не требуется, поэтому нажмите кнопку Добавить.

При нажатии кнопки Добавить Visual Web Developer создаст новый шаблон представления index. cshtml для нас в каталоге \Виевс\хоме, создавая папку, если она еще не создана.

Имя и расположение папки в файле index. cshtml важны и следуют соглашениям об именовании ASP.NET MVC по умолчанию. Имя каталога \Виевс\хоме соответствует контроллеру, который называется HomeController. Имя шаблона представления — index соответствует методу действия контроллера, который будет отображать представление.

ASP.NET MVC позволяет нам избегать явного указания имени или расположения шаблона представления при использовании этого соглашения об именовании для возвращения представления. По умолчанию шаблон представления \Виевс\хоме\индекс.кштмл отображается при написании кода, подобного приведенному ниже, в HomeController:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

Visual Web Developer создал и открыл шаблон представления index. cshtml после нажатия кнопки "Добавить" в диалоговом окне "Добавление представления". Содержимое index. cshtml показано ниже.

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

Это представление использует синтаксис Razor, что более наглядно, чем обработчик представлений веб-форм, используемый в веб-формах ASP.NET и предыдущих версиях ASP.NET MVC. Обработчик представлений веб-форм по-прежнему доступен в ASP.NET MVC 3, но многие разработчики обнаружили, что подсистема представлений Razor очень хорошо подходит для разработки ASP.NET MVC.

Первые три строки задают заголовок страницы с помощью ViewBag. Title. Мы рассмотрим, как это работает в ближайшее время, но сначала будем обновлять текст заголовка текста и просматривать страницу. Обновите тег <H2>, чтобы сказать: «это Домашняя страница», как показано ниже.

@{
    ViewBag.Title = "Index";
}
<h2>This is the Home Page</h2>

При запуске приложения отображается новый текст, отображаемый на домашней странице.

Использование макета для общих элементов сайта

Большинство веб-сайтов имеют содержимое, которое совместно используется несколькими страницами: Навигация, нижние колонтитулы, изображения логотипа, ссылки на таблицы стилей и т. д. Подсистема представлений Razor упрощает управление с помощью страницы с именем _Layout. cshtml, которая автоматически создается для нас в папке/Виевс/Шаред.

Дважды щелкните эту папку, чтобы просмотреть ее содержимое, как показано ниже.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"     
            type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
            type="text/javascript"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

Содержимое наших индивидуальных представлений будет отображаться командой @RenderBody() и любым общим содержимым, которое мы хотим использовать вне области, которое можно добавить в разметку _Layout. cshtml. Нам потребуется, чтобы в нашем музыкальном магазине MVC имелся общий заголовок со ссылками на нашу домашнюю страницу и область хранения на всех страницах сайта, поэтому мы добавим его в шаблон непосредственно перед инструкцией @RenderBody().

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"
type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>
            ASP.NET MVC MUSIC STORE</h1>
        <ul id="navlist">
            <li class="first"><a href="/"
id="current">Home</a></li>
            <li><a
href="/Store/">Store</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>

Обновление таблицы стилей

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

Обновленный файл CSS и изображения включены в каталог содержимого Мвкмусиксторе-Ассетс. zip, который доступен в MVC-Music-Store. Мы выберем оба из них в проводнике Windows и разместите их в папке содержимого нашего решения в Visual Web Developer, как показано ниже:

Вам будет предложено подтвердить, нужно ли перезаписать существующий файл Site. CSS. Нажмите кнопку Да.

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

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

  • Давайте посмотрим, что изменилось: метод действия индекса HomeController, найденный и отображающий шаблон \Виевс\хоме\индекс.кштмлвиев, несмотря на то, что наш код называется «Return View ()», так как наш шаблон представления, за которым следует стандартное соглашение об именовании.
  • На домашней странице отображается простое приветственное сообщение, которое определено в шаблоне представления \Виевс\хоме\индекс.кштмл.
  • Домашняя страница использует наш шаблон _Layout. cshtml, поэтому приветственное сообщение содержится в макете HTML для стандартного сайта.

Использование модели для передачи информации в наше представление

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

В шаблоне модель-представление-контроллер термин модель относится к объектам, которые представляют данные в приложении. Часто объекты модели соответствуют таблицам в базе данных, но им не нужно.

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

Сначала мы создадим некоторые классы модели для представления жанров и альбомов в магазине. Начнем с создания класса жанра. Щелкните правой кнопкой мыши папку Models в проекте, выберите пункт "добавить класс" и назовите файл "Genre.cs".

Затем добавьте свойство имени общедоступной строки в созданный класс:

public class Genre
{
    public string Name { get; set; }
}

Примечание. на случай, если вы заинтересовались, в нотации C#{Get; Set;} используется функция автоматического внедрения свойств. Это дает нам преимущества свойства, не требуя объявления резервного поля.

Затем выполните те же действия, чтобы создать класс альбома (с именем Album.cs) с заголовком и свойством жанра:

public class Album
{
    public string Title { get; set; }
    public Genre Genre { get; set; }
}

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

Мы начнем с изменения действия Store Details, чтобы показать сведения об одном альбоме. Добавьте оператор "using" в начало класса стореконтроллерс , чтобы включить пространство имен Мвкмусиксторе. Models, поэтому нам не нужно вводить Мвкмусиксторе. Models. альбом каждый раз, когда нужно использовать класс альбома. Раздел "using" этого класса теперь должен выглядеть так, как показано ниже.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.Models;

Далее мы изменим действие контроллера сведений таким образом, чтобы оно возвращало ActionResult, а не строку, как в случае с методом индекса HomeController.

public ActionResult Details(int id)

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

public ActionResult Details(int id)
 {
    var album = new Album { Title = "Album " + id };
    return View(album);
 }

Примечание. Если вы не знакомы с C#, можно предположить, что использование var означает, что наша переменная альбома имеет позднюю привязку. Это неверно: C# компилятор использует определение типа на основе того, что мы присваиваем переменной, чтобы определить, что альбом имеет тип "альбом" и компилирует переменную локального альбома в качестве типа альбома, поэтому мы получаем проверку во время компиляции и поддержку редактора кода Visual Studio.

Теперь создадим шаблон представления, который использует наш альбом для создания ответа HTML. Прежде чем делать это, необходимо выполнить сборку проекта, чтобы диалоговое окно добавления представления знало о новом созданном классе альбома. Чтобы построить проект, выберите пункт меню Отладка ⇨ сборка Мвкмусиксторе (для дополнительного кредита можно использовать сочетание клавиш CTRL + SHIFT + B для построения проекта).

Теперь, когда мы настроили наши вспомогательные классы, мы готовы к созданию нашего шаблона представления. Щелкните правой кнопкой мыши в методе Details и выберите "добавить представление..." в контекстном меню.

Мы создадим новый шаблон представления, как мы делали раньше с HomeController. Так как мы создаем его из Стореконтроллер, он будет создан по умолчанию в \Виевс\сторе\индекс.кштмл-файле.

В отличие от ранее, будет установлен флажок "создать строго типизированное представление". Затем мы будем выбирать наш класс «альбом» в разделе «View Data-Class» Drop-довнлист. Это приведет к созданию в диалоговом окне "Добавление представления" шаблона представления, ожидающего, что объект альбома будет передан ему для использования.

При нажатии кнопки "Добавить" будет создан шаблон представления \Виевс\сторе\детаилс.кштмл, содержащий следующий код.

@model MvcMusicStore.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>Details</h2>

Обратите внимание на первую строку, которая указывает, что это представление строго типизировано для нашего класса альбома. Подсистема представления Razor понимает, что ей был передан объект альбома, поэтому мы можем легко получить доступ к свойствам модели и даже воспользоваться преимуществами IntelliSense в редакторе Visual Web Developer.

Обновите тег <H2>, чтобы отобразить свойство заголовка альбома, изменив эту строку следующим образом.

<h2>Album: @Model.Title</h2>

Обратите внимание, что IntelliSense активируется при вводе точки после ключевого слова @Model, отображая свойства и методы, поддерживаемые классом альбома.

Теперь повторно запустите наш проект и перейдите по URL-адресу/Store/Details/5. Мы увидим сведения о следующем альбоме, как показано ниже.

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

public ActionResult Browse(string genre)
 {
    var genreModel = new Genre { Name = genre };
    return View(genreModel);
 }

Щелкните правой кнопкой мыши метод browse и выберите "добавить представление..." в контекстном меню добавьте строго типизированное представление добавление строго типизированного в класс жанра.

Обновите элемент <H2> в коде представления (в/Виевс/Сторе/бровсе.кштмл), чтобы отобразить сведения о жанре.

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>

Теперь перейдем к нашему проекту и перейду к/Сторе/бровсе? Жанр = URL-адрес Disco. Появится страница Обзор, как показано ниже.

Наконец, сделаем немного более сложное обновление метода действия индекса Store и просмотр, чтобы отобразить список всех жанров в нашем магазине. Это делается с помощью списка жанров в качестве объекта модели, а не только для одного жанра.

public ActionResult Index()
{
    var genres = new List<Genre>
    {
        new Genre { Name = "Disco"},
        new Genre { Name = "Jazz"},
        new Genre { Name = "Rock"}
    };
    return View(genres);
 }

Щелкните правой кнопкой мыши метод действия сохранить индекс и выберите Добавить представление как прежде, выберите жанр в качестве класса модели и нажмите кнопку Добавить.

Сначала мы изменим объявление @model, чтобы указать, что представление будет ожидать несколько объектов жанра, а не только один. Измените первую строку/Сторе/индекс.кштмл на Read следующим образом:

@model IEnumerable<MvcMusicStore.Models.Genre>

Это указывает ядру представления Razor, что он будет работать с объектом модели, который может содержать несколько объектов-жанров. Мы используем<жанра IEnumerable> а не список<жанр>, так как он более универсальный, что позволяет нам изменить наш тип модели позже на любой тип объектов, поддерживающий интерфейс IEnumerable.

Далее мы выполним перебор объектов жанра в модели, как показано в приведенном ниже коде представления.

@model IEnumerable<MvcMusicStore.Models.Genre>
@{
    ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
    Select from @Model.Count()
genres:</p>
<ul>
    @foreach (var genre in Model)
    {
        <li>@genre.Name</li>
    }
</ul>

Обратите внимание, что у нас есть полная поддержка IntelliSense по мере ввода этого кода, поэтому при вводе «@Model». Мы видим все методы и свойства, поддерживаемые IEnumerable типа жанра.

В рамках цикла foreach Visual Web Developer знает, что каждый элемент относится к типу жанра, поэтому мы видим IntelliSense для каждого типа жанра.

Затем функция формирования шаблонов проверила объект жанра и определила, что каждый из них будет иметь свойство Name, поэтому он просматривает и записывает их. Он также создает ссылки Edit, Details и DELETE для каждого отдельного элемента. Мы будем использовать их позже в нашем Менеджере магазина, но теперь нам хотелось бы иметь простой список.

При запуске приложения и переходе к/Store видно, что отображается количество и список жанров.

Наш URL-адрес/Store, в котором в настоящее время перечислены жанры, просто отображает имена жанров простым текстом. Давайте изменим это так, чтобы вместо обычного текста имена жанров были связаны с соответствующим URL-адресом/Сторе/бровсе, поэтому при щелчке по жанру музыки, например "Disco", будет выполнен переход к URL-адресу/Сторе/бровсе? жанр = Disco. Мы можем обновить наш шаблон представления \Виевс\сторе\индекс.кштмл, чтобы вывести эти ссылки с помощью кода, как показано ниже (не вводите это в, мы будем улучшать его) :

<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

Это работает, но может привести к возникновению проблем позже, так как оно полагается на жестко закодированную строку. Например, если мы хотим переименовать контроллер, нам придется искать ссылки, которые необходимо обновить, в нашем коде.

Альтернативным подходом, который мы можем использовать, является использование преимуществ вспомогательного метода HTML. ASP.NET MVC включает вспомогательные методы HTML, доступные из нашего кода шаблона представления для выполнения различных распространенных задач, как это происходит. Вспомогательный метод HTML. ActionLink () особенно полезен и упрощает создание HTML-<> ссылок и позаботится о том, что URL-пути правильно кодируются URL-адрес.

В HTML. ActionLink () имеется несколько различных перегрузок, позволяющих указать столько сведений, сколько требуется для ссылок. В самом простом случае вы получите только текст ссылки и метод действия, чтобы переходить по гиперссылке на клиенте. Например, можно создать ссылку на метод Index ()/Сторе/на странице сведений о магазине, щелкнув текст ссылки "переход к индексу магазина", используя следующий вызов:

@Html.ActionLink("Go
to the Store Index", "Index")

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

Однако наши ссылки на страницу обзора должны передать параметр, поэтому мы будем использовать другую перегрузку метода HTML. ActionLink, принимающую три параметра:

    1. Текст ссылки, в котором отображается название жанра
    1. Имя действия контроллера (обзор)
    1. Значения параметров маршрута, в которых указывается как имя (жанр), так и значение (название жанра).

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

<ul>
    @foreach (var genre in Model)
    {
        <li>@Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
    }
</ul>

Теперь, когда мы снова выполним проект и доступ к URL-адресу/Сторе/, мы увидим список жанров. Каждый жанр является гиперссылкой. когда вы ее щелкнули, мы отпустим свой URL-адрес/Сторе/бровсе? жанр = [жанр] .

HTML-код для списка жанров выглядит следующим образом:

<ul>
    <li><a href="/Store/Browse?genre=Disco">Disco</a>
</li>
    <li><a href="/Store/Browse?genre=Jazz">Jazz</a>
</li>
    <li><a href="/Store/Browse?genre=Rock">Rock</a>
</li>
</ul>