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

ASP_NET_MVC_4_Framework_s_primerami_na_C_dlya_p

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

ViewBag.Cities = new string[] {"New York", "London", "Paris"}; string message = "This is an HTML element: <input>";

return View((object) message);

}

public ActionResult CreatePerson()

{

return View(new Person {IsApproved = true});

}

[HttpPost]

public ActionResult CreatePerson(Person person)

{

return View("DisplayPerson", person);

}

}

}

Мы создали представление DisplayPerson.cshtml в папке /Views/Home; содержимое этого файла показано в листинге 20-7.

Листинг 20-7: Содержимое файла DisplayPerson.cshtml

@model HelperMethods.Models.Person @{

ViewBag.Title = "DisplayPerson";

}

<h2>DisplayPerson</h2> <div class="dataElem">

@Html.Label("PersonId")

@Html.Display("PersonId")

</div>

<div class="dataElem">

@Html.Label("FirstName")

@Html.Display("FirstName")

</div>

<div class="dataElem">

@Html.LabelFor(m => m.LastName) @Html.DisplayFor(m => m.LastName)

</div>

<div class="dataElem">

@Html.LabelFor(m => m.Role) @Html.DisplayFor(m => m.Role)

</div>

<div class="dataElem">

@Html.LabelFor(m => m.BirthDate) @Html.DisplayFor(m => m.BirthDate)

</div>

Чтобы увидеть вывод этого представления, запустите приложение, перейдите по ссылке /Home/CreatePerson, заполните форму и нажмите кнопку Submit. Результат показан на рисунке 20- 3, и, как видите, мы сделали небольшой шаг назад, потому что вспомогательные методы Label и LabelFor используют имена свойств в качестве текста для меток.

511

Рисунок 20-3: Создаем нередактируемые элементы для объекта Person, используя вспомогательные методы

Вывод этих вспомогательных методов вы можете увидеть в листинге 20-8. Обратите внимание на то, что методы Display и DisplayFor не генерируют элементы HTML по умолчанию, они просто отображают значение свойства, с которым работают.

Листинг 20-8: HTML, созданный представлением DisplayPerson

<!DOCTYPE html> <html>

<head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width" /> <title>DisplayPerson</title>

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

label {

display: inline-block; width: 100px;

}

.dataElem { margin: 5px;

}

</style>

</head>

<body>

<h2>DisplayPerson</h2> <div class="dataElem">

<label for="PersonId">PersonId</label> 100

</div>

<div class="dataElem">

<label for="FirstName">FirstName</label> Adam

</div>

<div class="dataElem">

<label for="LastName">LastName</label> Freeman

</div>

<div class="dataElem">

512

<label for="Role">Role</label> Admin

</div>

<div class="dataElem">

<label for="BirthDate">BirthDate</label> 01/01/0001 00:00:00

</div>

</body>

</html>

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

Используем шаблонные вспомогательные методы для целой модели

Мы использовали шаблонные вспомогательные методы, которые генерируют вывод для одного свойства, но MVC Framework также определяет методы, которые работают с целыми объектами; этот процесс известен как формирование шаблонов (scaffolding). Вспомогательные методы для моделей показаны в таблице 20-2.

Таблица 20-2: Вспомогательные методы для моделей

Вспомогательный

Пример

 

Описание

метод

 

 

 

 

 

 

 

 

DisplayForModel

Html.DisplayForModel()

 

Визуализирует нередактируемые элементы для

 

объекта модели.

 

 

 

 

 

 

 

EditorForModel

Html.EditorForModel()

 

Визуализирует редактируемые элементы для

 

объекта модели.

 

 

 

 

LabelForModel

Html.LabelForModel()

 

Визуализирует HTML-элемент <label> со ссылкой

 

на объект модели.

 

 

 

В листинге 20-9 показано, как с помощью вспомогательных методов LabelForModel и EditorForModel можно упростить представление CreatePerson.cshtml.

Листинг 20-9: Применяем вспомогательные методы для моделей в представлении CreatePerson

@model HelperMethods.Models.Person @{

ViewBag.Title = "CreatePerson"; Html.EnableClientValidation(false);

}

<h2>CreatePerson: @Html.LabelForModel()</h2>

@using (Html.BeginRouteForm("FormRoute", new { }, FormMethod.Post, new { @class = "personClass", data_formType = "person" }))

{

@Html.EditorForModel()

<input type="submit" value="Submit" />

}

Результат применения вспомогательных методов для моделей показан на рисунке 20-4. Напомним еще раз, что пока вывод вспомогательных методов не вполне соответствует нашим ожиданиям. Метод LabelForModel сгенерировал не очень хорошие метки; хотя сейчас отображается больше свойств объекта модели Person, чем мы определили вручную в предыдущих примерах, но отображаются они не все (например, нет свойства Address) и не лучшим способом (например, свойство Role лучше отображать как элемент select, а не input).

513

Рисунок 20-4: Создаем редактируемые элементы для объекта модели Person с помощью вспомогательных методов для моделей

Часть проблемы заключается в том, что сгенерированный этими методами HTML не соответствует стилям CSS, которые мы добавили в файл /Views/Shared/_Layout.cshtml в главе 19. Ниже приведен пример кода HTML, сгенерированного для свойства FirstName:

<div class="editor-label">

<label for="FirstName">FirstName</label> </div>

<div class="editor-field">

<input class="text-box single-line" id="FirstName" name="FirstName" type="text" value="" />

</div>

Чтобы привести в порядок наше представление, мы изменим стили так, чтобы они соответствовали значениям атрибутов CSS class, которые были добавлены к элементам div и input вспомогательными методами. В листинге 20-10 показаны изменения, которые мы внесли в файл

_Layout.cshtml.

514

Листинг 20-10: Изменяем стили CSS, определенные в файле _Layout.cshtml

<!DOCTYPE html> <html>

<head>

<meta charset="utf-8" />

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

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

label { display: inline-block; width: 100px;}

.dataElem { margin: 5px;} h2 > label {width: inherit;}

.editor-label, .editor-field {float: left;}

.editor-label, .editor-label label, .editor-field input {height: 20px;}

.editor-label {clear: left;}

.editor-field { margin-left: 10px; margin-top: 10px;} input[type=submit] { float: left; clear: both; margin-top: 10px;}

.column { float: left; margin: 10px;}

</style>

</head>

<body>

@RenderBody()

</body>

</html>

Эти новые стили приводят страницу в соответствие с макетом, который мы использовали в предыдущих примерах, как показано на рисунке 20-5. (Мы также добавили некоторые стили, которые понадобятся нам позже в этой главе).

Рисунок 20-5: Применяем стили к элементам, используя классы, определенные вспомогательными методами

515

Использование метаданных модели

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

Нельзя взваливать вину за такой результат на шаблонные вспомогательные методы; они генерируют HTML, основываясь на наиболее точных предположениях относительно того, что мы ожидаем. К счастью, с помощью метаданных модели мы можем предоставить вспомогательным методам информацию о том, как обрабатывать наши типы моделей. Метаданные записываются с помощью атрибутов C#, где значения атрибутов и параметров предоставляют различные инструкции вспомогательным методам представлений. Метаданные применяются к классу модели, к которому обращаются вспомогательные методы, когда генерируют элементы HTML. В следующих разделах мы продемонстрируем, как с помощью метаданных можно предоставлять инструкции вспомогательным методам для создания элементов label, display и editor.

Контролируем редактируемость и видимость свойств с помощью метаданных

Мы не хотим, чтобы пользователи могли видеть или редактировать свойство PersonId класса Person. В большинстве классов моделей есть по крайней мере одно такое свойство, которое часто связано с механизмом хранения – например, первичный ключ, который находится под контролем реляционной базы данных (что мы продемонстрировали, когда создавали приложение SportsStore).

Можно использовать атрибут HiddenInput, который сообщит вспомогательному методу, что необходимо отобразить как скрытое поле. В листинге 20-11 показано, как мы применили

HiddenInputAttribute к классу Person.

Листинг 20-11: Используем атрибут HiddenInput

using System;

using System.Web.Mvc;

namespace HelperMethods.Models

{

public class Person

{

[HiddenInput]

public int PersonId { get; set; }

public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public Address HomeAddress { get; set; } public bool IsApproved { get; set; } public Role Role { get; set; }

}

// ...other types omitted from Listing 20-for brevity...

}

Когда к свойству применен этот атрибут, вспомогательные методы Html.EditorFor и Html.EditorForModel будут визуализировать для него нередактируемый элемент. На рисунке 20-6 показан результат запуска приложения и перехода по ссылке к /Home/CreatePerson.

516

Рисунок 20-6: Визуализация нередактируемого элемента для свойства

Значение свойства PersonId выводится, но пользователь не может его редактировать. Для этого свойства генерируется следующий HTML:

<div class="editor-field"> 0

<input id="PersonId" name="PersonId" type="hidden" value="0" /> </div>

Значение свойства (в данном случае 0) просто визуализируется, но вспомогательный метод также создает для него скрытый элемент input; это полезный элемент в формах HTML, потому что он гарантирует, что при отправке формы мы предоставляем значение для данного свойства (мы вернемся к этой теме, когда будем рассматривать связывание данных в главе 22 и валидацию в главе 23). Если мы хотим полностью скрыть свойство, можно установить свойству DisplayValue в атрибуте HiddenInput значение false, как показано в листинге 20-12.

Листинг 20-12: Скрываем свойство с помощью атрибута HiddenInput

public class Person

{

[HiddenInput(DisplayValue = false)] public int PersonId { get; set; }

public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public Address HomeAddress { get; set; } public bool IsApproved { get; set; } public Role Role { get; set; }

}

Когда мы используем вспомогательный метод Html.EditorForModel для объекте Person, он создает скрытое поле ввода, чтобы при отправке формы значение свойства PersonId также было отправлено, но метка и числовое значение были опущены. Это имеет такой же эффект, как и скрытие свойства PersonId от пользователя, как показано на рисунке 20-7.

517

Рисунок 20-7: Скрытие свойств объекта модели от пользователя

Если вы хотите визуализировать HTML для отдельных свойств, можно создать скрытый элемент input для свойства PersonId с помощью вспомогательного метода Html.EditorFor:

@Html.EditorFor(m => m.PersonId)

Свойство HiddenInput обнаруживается, и если DisplayValue имеет значение true, то будет сгенерирован следующий код HTML:

<input id="PersonId" name="PersonId" type="hidden" value="1" />

Исключаем свойство из формирования шаблонов

Если вы не хотите создавать HTML для свойства, можно использовать атрибут ScaffoldColumn. В то время как атрибут HiddenInput включает значение свойства в скрытый элемент ввода, ScaffoldColumn означает, что свойство не будет использоваться при формировании шаблона. Вот пример использования атрибута:

[ScaffoldColumn(false)]

public int PersonId { get; set; }

Когда вспомогательный метод для модели увидит атрибут ScaffoldColumn, он полностью пропустит это свойство; для него не будет создан скрытый элемент ввода, и информация из этого свойства не будет включена в HTML. Сгенерированный HTML будет таким же, как если бы мы использовали атрибут HiddenInput, но при отправки формы значение для этого свойства отправляться не будет (это может оказывать влияние на связывание данных, которое мы обсудим позже в этой главе). Атрибут ScaffoldColumn не влияет на вспомогательные методы, работающие с одним свойством,

такие как EditorFor. Если мы вызовем в представлении @Html.EditorFor(m => m.PersonId), для свойства PersonId будет создан элемент editor, даже если к нему применен атрибут

ScaffoldColumn.

518

Используем метаданные для создания элементов label

По умолчанию вспомогательные методы Label, LabelFor, LabelForModel и EditorForModel

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

@Html.LabelFor(m => m.BirthDate)

генерируется следующий элемент HTML:

<label for="BirthDate">BirthDate</label>

Конечно, мы не всегда хотим отображать пользователю названия свойств.Для этого можно применить атрибут DisplayName из пространства имен System.ComponentModel.DataAnnotations и

передать в него значение для свойства Name. В листинге 20-13 показано, как мы применили этот атрибут к классу Person.

Листинг 20-13: Используем атрибут DisplayName для создания метки

using System;

using System.Web.Mvc;

using System.ComponentModel.DataAnnotations; using System.ComponentModel;

namespace HelperMethods.Models

{

[DisplayName("New Person")] public class Person

{

[HiddenInput(DisplayValue = false)] public int PersonId { get; set; }

[Display(Name

= "First")]

get; set; }

public string

FirstName {

[Display(Name

= "Last")]

 

public string

LastName { get; set; }

[Display(Name

= "Birth Date")]

public DateTime BirthDate

{ get; set; }

public Address HomeAddress { get; set; }

[Display(Name = "Approved")]

public bool IsApproved { get; set; }

public Role Role { get; set; }

}

// ...other types omitted from Listing 20-for brevity...

}

Когда вспомогательный метод будет визуализировать элемент label для свойства BirthDate, он обнаружит атрибут Display и будет использовать значение параметра Name в качестве текста метки, например:

<label for="BirthDate">Birth Date</label>

Вспомогательные методы также распознают атрибут DisplayName, который можно найти в пространстве имен System.ComponentModel. Этот атрибут можно применять к классам, что

519

позволяет нам использовать вспомогательный метод Html.LabelForModel – в листинге показано, как мы применили этот атрибут к классу Person. (Атрибут DisplayName можно применить и к свойствам, но мы, как правило, используем его только для классов моделей – просто по привычке). Результат применения атрибутов Display и DisplayName показан на рисунке 20-8.

Рисунок 20-8: Используем атрибуты Display и DisplayName для создания меток

Используем метаданные для значений данных

С помощью метаданных можно предоставить инструкции относительно того, как должно отображаться свойство модели. Для нашего свойства BirthDate отображается время, хотя мы хотели бы отображать для него только дату, и, чтобы решить эту проблему, мы будем использовать метаданные. Отображаемые значения данных контролируются атрибутом DataType. В листинге 2014 вы можете увидеть, как мы применили его к классу Person.

Листинг 20-14: Применяем атрибут DataType к классу Person

[DisplayName("New Person")] public class Person

{

[HiddenInput(DisplayValue = false)] public int PersonId { get; set; }

[Display(Name

= "First")]

public

string

FirstName { get; set; }

[Display(Name

= "Last")]

public

string

LastName { get; set; }

[Display(Name = "Birth Date")]

[DataType(DataType.Date)]

520

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