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

ASP_NET_MVC_4_Framework_s_primerami_na_C_dlya_p

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

<tr>

<th>Property</th>

<th>Value</th>

</tr>

</thead>

<tbody>

<tr>

<td>Name</td> <td>@Model.Name</td>

</tr>

<tr>

<td>Price</td> <td>@Model.Price</td>

</tr>

<tr>

<td>Stock Level</td> <td>@ViewBag.ProductCount</td>

</tr>

</tbody>

</table>

Для этого примера мы создали простую HTML таблицу и использовали свойства объекта модели и ViewBag для заполнения ячеек значениями. На рисунке 5-12 вы можете увидеть результат запуска приложений и переход по адресу /Home/DemoExpression. Это всего лишь еще одна демонстрация основных Razor выражений, которые мы до сих пор использовали в примерах.

Рисунок 5-12: Использование основных выражений Razor для вставки значений данных в HTML разметку

111

Результат не особо красивый, потому что мы не применяли никаких CSS стилей к HTML элементам, которые генерируют представление и макет. Однако этот пример служит для четкого понимания того, каким образом могут быть использованы основные Razor выражения для отображения данных, передаваемых от метода действия к представлению.

Установка значений атрибутов

Все наши примеры до сих пор касались содержания элементов, но вы также можете использовать Razor выражения для установки значений атрибутов элементов. В листинге 5-15 показано, как мы изменили представление DemoExpression, чтобы использовать ViewBag свойства для значений атрибутов. Способ, которым Razor обрабатывает атрибуты в MVC 4, довольно разумный и интересный, и это одна из тех областей, которые были улучшены после MVC 3.

Листинг 5-15: Использование Razor выражения для установки значения атрибута

@model Razor.Models.Product @{

ViewBag.Title = "DemoExpression"; Layout = "~/Views/_BasicLayout.cshtml";

}

<table>

<thead>

<tr>

<th>Property</th>

<th>Value</th>

</tr>

</thead>

<tbody>

<tr>

<td>Name</td>

<td>@Model.Name</td>

</tr>

<tr>

<td>Price</td>

<td>@Model.Price</td>

</tr>

<tr>

<td>Stock Level</td> <td>@ViewBag.ProductCount</td>

</tr>

</tbody>

</table>

<div data-discount="@ViewBag.ApplyDiscount" data-express="@ViewBag.ExpressShip" data-supplier="@ViewBag.Supplier">

The containing element has data attributes </div>

Discount:<input type="checkbox" checked="@ViewBag.ApplyDiscount" /> Express:<input type="checkbox" checked="@ViewBag.ExpressShip" /> Supplier:<input type="checkbox" checked="@ViewBag.Supplier" />

Мы начали с использования основных Razor выражений для установки значений некоторых атрибутов data элемента div. data-атрибуты, которые являются атрибутами, чьи имена начинаются с data-, были неформальным способом создания пользовательских атрибутов в течение многих лет и стали стандартом в HTML5. Мы использовали значения свойств ViewBag ApplyDiscount, ExpressShip и Supplier, чтобы установить значения этих атрибутов.

Запустите пример приложения, выберите нужный метод действия и посмотрите на исходный HTML, который был использован для отображения страницы. Вы увидите, что Razor установил значения атрибутов следующим образом:

112

<div data-discount="False" data-express="True" data-supplier=""> The containing element has data attributes

</div>

Значения False и True соответствуют булевым ViewBag значениям, но Razor сделал кое-что разумное для свойства, чье значение равно null, а именно, представил пустую строку.

Но все становится гораздо более интересным, когда мы посмотрим на второе наше дополнение в представлении: это набор чекбоксов, чей атрибут checked установлен на те же самые ViewBag свойства, которые мы использовали для атрибутов data. HTML, который представил Razor, выглядит следующим образом:

Discount: <input type="checkbox" />

Express: <input type="checkbox" checked="checked" />

Supplier: <input type="checkbox" />

В MVC 4 Razor стал понимать, как используется такие атрибуты как checked, где наличие атрибута, а не его значение, меняет конфигурацию элемента. Если бы Razor вставили False, или null, или пустую строку в качестве значения атрибута checked, тогда в чекбоксе, который отображает браузер, стояла бы галочка. Вместо этого Razor полностью удаляет атрибут из элемента, если значение равно false или null, создавая нужный результат, как показано на рисунке 5-13.

Рисунок 5-13: Результат удаления атрибутов, чье присутствие влияет на элемент

113

Использование условных операторов

Razor способен обрабатывать условные операторы, что обозначает, что мы можем подгонять выходные данные наших представлений, основываясь на значениях данных в нашем представлении. Мы собираемся добраться до самого сердца Razor, что позволяет нам создавать сложные и гибкие макетов, которые остаются простыми для понимания и поддержки. В листинге 5-16 мы обновили наш файл представления DemoExpression.cshtml, чтобы включить в него условный оператор.

Листинг 5-16: Использование условного оператора Razor

@model Razor.Models.Product @{

ViewBag.Title = "DemoExpression"; Layout = "~/Views/_BasicLayout.cshtml";

}

<table>

<thead>

<tr>

<th>Property</th>

<th>Value</th>

</tr>

</thead>

<tbody>

<tr>

<td>Name</td>

<td>@Model.Name</td>

</tr>

<tr>

<td>Price</td>

<td>@Model.Price</td>

</tr>

<tr>

<td>Stock Level</td>

<td>@switch ((int)ViewBag.ProductCount) { case 0:

@: Out of Stock break;

case 1:

<b>Low Stock (@ViewBag.ProductCount)</b> break;

default:

@ViewBag.ProductCount

break;

}

</td>

</tr>

</tbody>

</table>

Чтобы написать условный оператор, поместите символ @ в начале этого оператора, в данном примере перед ключевым словом C# switch. Блок кода заканчивается фигурной скобкой (}) так же, как и обычный блок кода C#.

Совет

Обратите внимание, что мы привели значение свойства ViewBag.ProductCount к int, чтобы использовать его с оператором switch. Это необходимо, поскольку оператор switch работает только с определенным набором типов, и он не может

оценить динамическое свойство без приведения типов.

114

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

...

<b>Low Stock (@ViewBag.ProductCount)</b>

...

@ViewBag.ProductCount

...

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

...

@: Out of Stock

...

Символ @: предотвращения Razor от интерпретации строки как C# выражения, что является поведением по умолчанию, когда он сталкивается с текстом. Вы можете увидеть результат использования нашего условного оператора на рисунке 5-14.

Рисунок 5-14: Использование условного оператора switch в представлении Razor

Условные операторы играют важную роль в Razor представлениях, потому что они позволяют подгонять содержание к значениям данных, которые представление получает от метода действия. В качестве дополнительного примера в листинге 5-17 показано добавление оператора if к представлению DemoExpression.cshtml – вы, естественно, знаете, что это очень широко используемый условный оператор.

115

Листинг 5-17: Использование условного оператора if в представлении Razor

@model Razor.Models.Product @{

ViewBag.Title = "DemoExpression"; Layout = "~/Views/_BasicLayout.cshtml";

}

<table>

<thead>

<tr>

<th>Property</th>

<th>Value</th>

</tr>

</thead>

<tbody>

<tr>

<td>Name</td>

<td>@Model.Name</td>

</tr>

<tr>

<td>Price</td>

<td>@Model.Price</td>

</tr>

<tr>

<td>Stock Level</td>

<td>@if (ViewBag.ProductCount == 0) { @:Out of Stock

}else if (ViewBag.ProductCount == 1) { <b>Low Stock (@ViewBag.ProductCount)</b>

}else {

@ViewBag.ProductCount

}

</td>

</tr>

</tbody>

</table>

Этот условный оператор дает тот же результат, что и switch, но мы просто хотели показать, как вы можете связывать условные операторы C# с Razor представлениями. Мы объясняем, как это все работает, в главе 18, когда мы более углубленно рассмотрим представления.

Перечисление содержимого массивов и коллекций

При написании MVC приложений вам часто будет нужно перечислять содержимое массива или другого вида коллекции объектов, и генерировать подробный контент каждого из них. Чтобы показать, как это делается, мы определили новый метод действия DemoArray в контроллере Home, который вы можете увидеть в листинге 5-18.

Листинг 5-18: Метод действия DemoArray

using Razor.Models; using System;

using System.Collections.Generic; using System.Web.Mvc;

namespace Razor.Controllers

{

public class HomeController : Controller

{

Product myProduct = new Product

{

ProductID = 1,

Name = "Kayak",

Description = "A boat for one person",

116

Category = "Watersports", Price = 275M

}; // ...другие методы действия опущены для краткости...

public ActionResult DemoArray()

{

Product[] array = {

= "Kayak", Price = 275M},

new Product {Name

new Product {Name

= "Lifejacket", Price = 48.95M},

new Product {Name

= "Soccer ball", Price = 19.50M},

new Product {Name

= "Corner flag", Price = 34.95M}

};

 

return View(array);

 

}

}

}

Этот метод действия создает объект Product[], который содержит несколько простых значений данных, и передает его методу View, и эти данные показываются при помощи представления по умолчанию.

Visual Studio не предлагает опции для массивов и коллекций при создании представления, поэтому вам придется вручную ввести информацию о требуемом типе в диалоговом окне Add View. Вы можете увидеть, как мы сделали это, на рисунке 5-15. Тут показано, как мы создали представление

DemoArray.cshtml и указали, что тип модели представления – это Razor.Models.Product[].

Рисунок 5-15: Установка вручную типа модели представления для строго типизированного представления

117

Вы можете увидеть содержимое файла представления DemoArray.cshtml в листинге 5-19, куда включены дополнения, которые мы сделали, чтобы показать информацию по элементам массива пользователи.

Листинг 5-19: Содержимое файла DemoArray.cshtml

@model Razor.Models.Product[]

@{

ViewBag.Title = "DemoArray";

Layout = "~/Views/_BasicLayout.cshtml";

}

@if (Model.Length > 0) { <table>

<thead>

<tr>

<th>Product</th>

<th>Price</th>

</tr>

</thead>

<tbody>

@foreach (Razor.Models.Product p in Model) { <tr>

<td>@p.Name</td> <td>$@p.Price</td>

</tr>

}

</tbody>

</table>

}else {

<h2>No product data</h2>

}

Мы использовали оператор @if, чтобы менять содержание в зависимости от длины массива, с которым мы работаем, и оператор @foreach, чтобы перечислить содержимое массива и создать строку в HTML таблицу для каждого из элементов. Вы видите, как эти выражения соответствуют своим C# копиям, и как мы создали локальную переменную р в цикле foreach, а затем обратились к ее свойствам, используя Razor выражения @p.Name и @p.Price.

В результате мы получаем элемент h2, если массив пуст, или, в противном случае, создаем одну строку для каждого элемента массива в HTML таблице. Поскольку в этом примере наши данные являются статическими, вы всегда будете видеть один и тот же результат, который представлен на рисунке 5-16.

Рисунок 5-16: Генерирование элементов при помощи оператора foreach

118

Работа с пространством имен

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

...

@foreach (Razor.Models.Product p in Model) {

...

Это может раздражать в сложных представлениях, где у вас будет много ссылок на модели представления и другие классы. Мы можем привести в порядок представления при помощи выражения @using, чтобы вставить пространство имен в контекст, как и для обычного C# класса. В листинге 5-20 показано, как мы применили выражение @using для представления DemoArray.cshtml, которое мы создали ранее.

Листинг 5-20: Применение выражения @using

@using Razor.Models @model Product[]

@{

ViewBag.Title = "DemoArray";

Layout = "~/Views/_BasicLayout.cshtml";

}

@if (Model.Length > 0) { <table>

<thead>

<tr>

<th>Product</th>

<th>Price</th>

</tr>

</thead>

<tbody>

@foreach (Product p in Model) { <tr>

<td>@p.Name</td> <td>$@p.Price</td>

</tr>

}

</tbody>

</table> } else {

<h2>No product data</h2>

}

Представление может содержать несколько выражений @using. Мы использовали выражение @using, чтобы импортировать пространство имен Razor.Models, что обозначает, что мы можем удалить пространство имен из выражения @model и из цикла foreach.

Резюме

В этой главе мы показали вам движок представления Razor и как он может быть использован для генерации HTML. Мы показали вам, как обратиться к данным, передаваемым из контроллера через объект модели представления и ViewBag, и мы показали вам, как Razor выражения могут быть использованы для создания ответов для пользователя на основе данных, с которыми вы работаете. Вы увидите много различных примеров того, как может быть использован Razor, в остальной части книги, и мы подробно расскажем, как работает механизм представлений MVC, в главе 18. В следующей главе мы опишем важные инструменты разработки и тестирования, которые лежат в основе MVC фреймворка и которые помогут вам существенно улучшить ваши проекты.\

119

Важные инструменты MVC

В этой главе мы рассмотрим три инструмента, которые должны быть в арсенале каждого MVC программиста: контейнер внедрения зависимостей (DI), фреймворк для модульного тестирования и инструмент для мокинга (mock-объектов).

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

Как мы уже отмечали в главе 3, Ninject – наш предпочитаемый DI контейнер. Он простой, элегантный и легкий в использовании. Есть более сложные альтернативы, но нам нравится способ, которым работает Ninject, причем, с минимумом настроек. Мы считаем отправной точкой паттерны, а не закон, и мы нашли что легко подгонять наш DI с Ninject к различным проектам и рабочим процессам. Если вам не нравится Ninject, мы рекомендуем попробовать Unity, который является одной из альтернатив Microsoft.

Для модульного тестирования мы будем использовать то, что встроено в Visual Studio. Мы привыкли использовать NUnit, который является самым популярным .NET фреймворком для модульного тестирования, но Microsoft сделал большой рывок в улучшении поддержки модульного тестирования в Visual Studio (и в настоящее время включает ее в бесплатное выпуски Visual Studio). В результате этого фреймоворки для модульного тестирования, тесно интегрированы в остальную части IDE и они стали довольно хорошими.

Третий инструмент, выбранный нами, это Moq, который является набором мокинг инструментов. Мы используем Moq в создании реализаций интерфейсов для использования в наших модульных тестах. Программисты или любят, или ненавидят Moq; третьего не дано. Либо вы посчитаете синтаксис элегантным и выразительным, или вы будете проклинать его каждый раз при попытке использования. Если вам он не по душе, обратите внимание на Rhino Mocks, который является хорошей альтернативой.

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

Примечание

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

120

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