Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ASP_NET_MVC_4_Framework_s_primerami_na_C_dlya_p

.pdf
Скачиваний:
25
Добавлен:
19.03.2016
Размер:
17.66 Mб
Скачать

соответствовала новому типу модели представления. Нам осталось только вызвать наш вспомогательный метод HTML из представления, что показано в листинге 7-22.

Листинг 7-22: Вызываем вспомогательный метод HTML

@model SportsStore.WebUI.Models.ProductsListViewModel

@{

ViewBag.Title = "Products";

}

@foreach (var p in Model.Products)

{

<div class="item"> <h3>@p.Name</h3> @p.Description <h4>@p.Price.ToString("c")</h4>

</div>

}

<div class="pager">

@Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x })) </div>

Если вы запустите приложение, вы увидите, что появились ссылки на страницы, как показано на рисунке 7-14. Оформлены они довольно просто, но мы исправим это позже в этой главе. На данный момент важно то, что по ссылкам можно переходить с одной страницы на другую и просматривать товары в каталоге.

Рисунок 7-14: Отображаем навигационные ссылки

181

Почему просто не использовать GridView?

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

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

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

Улучшаем URL

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

http://localhost/?page=2

Чтобы их улучшить, мы можем создать схему по шаблону компонуемых URL. Компонуемый URL – это ссылка, которая имеет смысл для пользователя, например:

http://localhost/Page2

К счастью, в MVC очень легко изменять схему URL, поскольку она использует функцию маршрутизации ASP.NET. Для этого нам нужно только добавить новый роут в метод

RegisterRoutes в файле RouteConfig.cs, который вы найдете в папке App_Start. Изменения показаны в листинге 7-23.

Листинг 7-23: Добавляем новый роут

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

using System.Web.Routing;

namespace SportsStore.WebUI

{

public class RouteConfig

{

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

182

name: null,

url: "Page{page}",

defaults: new { Controller = "Product", action = "List" } );

routes.MapRoute( name: "Default",

url: "{controller}/{action}/{id}", defaults: new

{

controller = "Product", action = "List",

id = UrlParameter.Optional

}

);

}

}

}

Важно, чтобы вы добавили этот роут перед роутом Default, который уже есть в файле. Как вы увидите в главе 13, роуты обрабатываются в том порядке, в котором они указаны, а нам нужно, чтобы у нового роута был более высокий приоритет, чем у роута по умолчанию.

Это единственное изменение, которое понадобится, чтобы изменить схему URL. MVC Framework тесно интегрирована с функцией маршрутизации, и поэтому изменение вроде этого автоматически отражается в результате выполнения метода Url.Action (который мы используем в представлении List.cshtml для генерации ссылок на страницы). Если вы совершенно не знакомы с маршрутизацией, не волнуйтесь - мы подробно рассмотрим ее в главе 13. Если вы запустите приложение и перейдите на страницу, вы увидите новую схему URL в действии, как показано на рисунке 7-15.

Рисунок 7-15: Новая схема URL отображается в браузере

Применение стилей к контенту

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

Примечание

В этой части главы мы попросим вас добавить стили CSS, не объясняя их значение. Адам подробно описывает CSS в своей книге Руководство по HTML5 (Apress, 2011).

183

Мы реализуем классический дизайн с двумя колонками и заголовком, как показано на рисунке 7-16.

Рисунок 7-16: Целевой дизайн приложения SportsStore

Определяем общий контент в макете

В главе 5 мы объяснили, как работают макеты Razor и как их применять. Когда мы создавали представление List.cshtml для контроллера Product, мы попросили вас отметить флажком опцию Use a layout, но не заполнять поле, в котором определяется макет. В результате используется макет по умолчанию, _Layout.cshtml, который можно найти в папке Views/Shared проекта SportsStore.WebUI. Откройте этот файл и измените его содержание так, чтобы он соответствовал листингу 7-24.

Листинг 7-24: Изменяем стандартный макет Razor

<!DOCTYPE html> <html>

<head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title>

<link href="~/Content/Site.css" type="text/css" rel="stylesheet" /> </head>

<body>

<div id="header">

<div class="title">SPORTS STORE</div> </div>

<div id="categories">

We will put something useful here later </div>

<div id="content"> @RenderBody()

</div>

</body>

</html>

Примечание

Обратите внимание, что мы попросили вас удалить теги Razor @Styles и @Scripts из

представления. Это новые дополнения к Razor в MVC 4, и мы опишем их должным образом в главе 24, когда будем говорить о способах оптимизации контента, который ваше приложение MVC демонстрирует клиентам. На данный момент мы хотим сохранить все внимание на основных функциях MVC.

184

Добавляем стили CSS

Разметка HTML в листинге 7-24 является характерной для приложения ASP.NET MVC. Она простая и чисто семантическая. Он описывает контент, но ничего не говорит о том, как он должен быть расположен на экране. Мы будем использовать CSS, чтобы сообщить браузеру, как должны быть расположены элементы, которые мы только что добавили.

Visual Studio создает для нас файл CSS автоматически, если мы создаем проект MVC, используя опцию Basic. Этот файл, который называется Site.css, можно найти в папке Content проекта SportsStore.WebUI, и мы уже просили вас добавить в файл _Layout.cshtml ссылку на этот файл:

<link href="~/Content/Site.css" type="text/css" rel="stylesheet" />

Откройте файл Site.css и добавьте стили, показанные в листинге 7-25, в конец файла (не удаляйте содержимое, которое уже есть в Site.css). Вам не нужно набирать их вручную. Вы можете скачать дополнения CSS и весь остальной проект как часть кода, который прилагается к этой книге.

Листинг 7-25: Определяем CSS

BODY

{

font-family: Cambria, Georgia, "Times New Roman"; margin: 0;

}

DIV#header DIV.title, DIV.item H3, DIV.item H4, DIV.pager A

{

font: bold 1em "Arial Narrow", "Franklin Gothic Medium", Arial;

}

DIV#header

{

background-color: #444; border-bottom: 2px solid #111; color: White;

}

DIV#header DIV.title

{

font-size: 2em; padding: .6em;

}

DIV#content

{

border-left: 2px solid gray; margin-left: 9em;

padding: 1em;

}

DIV#categories

{

float: left; width: 8em; padding: .3em;

}

DIV.item

{

border-top: 1px dotted gray; padding-top: .7em; margin-bottom: .7em;

185

}

DIV.item:first-child

{

border-top: none; padding-top: 0;

}

DIV.item H3

{

font-size: 1.3em; margin: 0 0 .25em 0;

}

DIV.item H4

{

font-size: 1.1em; margin: .4em 0 0 0;

}

DIV.pager

{

text-align: right; border-top: 2px solid silver; padding: .5em 0 0 0; margin-top: 1em;

}

DIV.pager A

{

font-size: 1.1em; color: #666; text-decoration: none; padding: 0 .4em 0 .4em;

}

DIV.pager A:hover

{

background-color: Silver;

}

DIV.pager A.selected

{

background-color: #353535; color: White;

}

Если вы запустите приложение, то увидите, что мы уже немного улучшили внешний вид. Изменения показаны на рисунке 7-17.

Рисунок 7-17: Приложение SportsStore с улучшенным дизайном

186

Создаем частичное представление

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

Чтобы добавить частичное представление, кликните правой кнопкой мыши папку /Views/Shared в проекте SportsStore.WebUI и выберите Add - View из контекстного меню. Назовите представление ProductSummary. Мы хотим отобразить информацию о товаре, поэтому выберите класс Product из выпадающего меню класса Model или введите указанное имя класса. Отметьте флажком опцию

Create as a partial view, как показано на рисунке 7-18.

Рисунок 7-18: Создаем частичное представление

Нажмите кнопку Add, и Visual Studio создаст файл частичного представления по адресу Views/Shared/ProductSummary.cshtml. Частичное представление очень похоже на обычное, за исключением того, что когда оно визуализируется, оно создает фрагмент HTML, а не полный HTMLдокумент. Если вы откроете представление ProductSummary, то увидите, что оно содержит только директиву представления модели, которая является нашим классом доменной модели Product. Примените изменения, показанные в листинге 7-26.

Листинг 7-26: Добавляем разметку в частичное представление ProductSummary

@model SportsStore.Domain.Entities.Product

<div class="item"> <h3>@Model.Name</h3> @Model.Description <h4>@Model.Price.ToString("c")</h4>

</div>

187

Теперь нам необходимо обновить Views/Products/List.cshtml, чтобы он начал использовать частичное представление. Вы можете увидеть изменения в листинге 7-27.

Листинг 7-27: Используем частичное представление в List.cshtml

@model SportsStore.WebUI.Models.ProductsListViewModel

@{

ViewBag.Title = "Products";

}

@foreach (var p in Model.Products)

{

Html.RenderPartial("ProductSummary", p);

}

<div class="pager">

@Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x })) </div>

Мы взяли разметку, которая раньше была в цикле foreach в представлении List.cshtml, и перенесли ее в новое частичное представление. Мы вызываем частичное представление, используя вспомогательный метод Html.RenderPartial. Параметры – это имя представления и объект модели представления.

Совет

Метод RenderPartial не возвращает разметку HTML, как большинство других

вспомогательных методов. Вместо этого он записывает содержимое непосредственно в поток ответа, и именно поэтому мы должны вызывать его как полную строку C#, используя точку с запятой. Это более эффективно, чем помещение в буфер созданной частичным представлением разметки HTML, потому что потом она все равно будет записана в поток ответа. Если вы предпочитаете более последовательный синтаксис, используйте метод Html.Partial, который делает то же, что и метод RenderPartial, но возвращает фрагмент HTML и

может быть вызван как @Html.Partial("ProductSummary", р).

Использовать частичное представление – это хороший прием. Он не меняет внешний вид приложения. Если вы запустите его, вы увидите, что дисплей остался тем же, как показано на рисунке 7-19.

Рисунок 7-19: Применяем частичное представление

188

Резюме

В этой главе мы создали большую часть базовой инфраструктуры для приложения SportsStore. На данный момент в нем еще нет многих функций, которые вы могли бы продемонстрировать клиенту, но уже имеется начало доменной модели с хранилищем товаров, которое поддерживается SQL Server и Entity Framework. У нас есть один контроллер, ProductController, который может создавать списки товаров, разбитые на страницы, настроенный DI и чистая и понятная схема URL.

Если вам показалось, что в этой главе было слишком много настроек и мало прогресса, то следующая глава ее уравновесит. Теперь, когда мы разобрались с базовыми элементами, мы можем двигаться вперед и добавить все функции для работы клиента с приложением: навигацию по категориям, корзину и процесс оплаты.

189

SportsStore: навигация

В предыдущей главе мы создали основу инфраструктуры приложения SportsStore. Теперь мы будем использовать ее для добавления ключевых функций в приложение, и вы начнете видеть, как окупается тот труд и время, которое мы затратили на создание основы. Мы сможем легко и просто добавлять важные для работы с приложением функции. В процессе вы познакомитесь с некоторыми дополнительными возможностями, которые предоставляет MVC Framework.

Добавление элементов навигации

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

Расширим модель действия List в классе ProductController так, чтобы она могла фильтровать объекты Product в хранилище.

Пересмотрим и улучшим нашу схему URL и исправим стратегию изменения маршрута.

Создадим список категорий, который будет размещен в боковой панели сайта, подсветку текущей категории и ссылки на другие категории.

Фильтрация списка товаров

Мы начнем с расширения класса модели представления, ProductsListViewModel, который мы добавили в проект SportsStore.WebUI в предыдущей главе. Мы должны обеспечить связь выбранной на данный момент категории с представлением, чтобы визуализировать боковую панель, так что начнем с этого. Изменения показаны в листинге 8-1.

Листинг 8-1: Расширяем класс ProductsListViewModel

using System.Collections.Generic; using SportsStore.Domain.Entities; namespace SportsStore.WebUI.Models

{

public class ProductsListViewModel

{

public IEnumerable<Product> Products { get; set; } public PagingInfo PagingInfo { get; set; }

public string CurrentCategory { get; set; }

}

}

Мы добавили новое свойство под названием CurrentCategory. Далее мы обновим класс ProductController, чтобы метод действия List отфильтровывал объекты Product по категориям и использовал новое свойство, которое мы добавили к модели представления, чтобы указывать выбранную категорию. Изменения показаны в листинге 8-2.

Листинг 8-2: Добавляем поддержку категорий в метод действия List

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

using SportsStore.Domain.Abstract; using SportsStore.Domain.Entities; using SportsStore.WebUI.Models; namespace SportsStore.WebUI.Controllers

190

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]