Методические указания к выполнению учебной практики 2 курс

advertisement
Методические указания к выполнению учебной практики 2 курс
Необходимо
разработанного
создать
веб-приложение
windows-приложения.
Далее
на
основании
представлена
уже
существующего
пошаговая
инструкция
выполнения работы.
Архитектура веб-приложения
Назначение большинства веб-приложений – получение данных из базы и отображение
их пользователю. Затем пользователь выполняет какие-либо действия и система сохраняет
данные либо модифицирует их. Архитектура таких приложений является трехзвенной.
Трёхуровневая архитектура, или трёхзвенная архитектура — архитектурная
модель
программного
комплекса,
предполагающая
наличие
в
нём
трёх
компонентов: клиентского приложения, сервера приложений, к которому подключено
клиентское приложение, и сервера базы данных, с которым работает сервер приложений.
Рис 1.
Трехзвенная архитектура
Клиент — это интерфейсный компонент, который представляет первый уровень,
собственно приложение для конечного пользователя. Первый уровень не должен иметь
прямых связей с базой данных (по требованиям безопасности), быть нагруженным
основной бизнес-логикой
(по требованиям масштабируемости)
и
хранить состояние
приложения (по требованиям надежности). На первый уровень может быть вынесена и
обычно
выносится
простейшая
бизнес-логика:
интерфейсавторизации,
алгоритмы
шифрования, проверка вводимых значений на допустимость и соответствие формату,
несложные операции (сортировка, группировка, подсчет значений) с данными, уже
загруженными на терминал.
Сервер приложений располагается на втором уровне. На втором уровне сосредоточена
большая часть бизнес-логики. Вне его остаются фрагменты, экспортируемые на терминалы, а
также погруженные в третий уровень хранимые процедуры и триггеры.
Клиент и сервер «общаются» между собой с помощью запросов и ответов
(request/response)
при
этом
одновременно
с
запросом
передаются
параметры
запроса.Действия (команды, в т.ч. обработка данных) инициируются параметрами запросов.
Также с помощью параметров передаются необходимые данные.
Сервер базы данных обеспечивает хранение данных и выносится на третий уровень.
Обычно это стандартная реляционная или объектно-ориентированная СУБД. Если третий
уровень представляет собой базу данных вместе с хранимыми процедурами, триггерами и
схемой, описывающей приложение в терминах реляционной модели, то второй уровень
строится как программный интерфейс, связывающий клиентские компоненты с прикладной
логикой базы данных.
Шаблон ASP.NETMVC
Для настольных приложений шаблон проектирования Model-View-Controller (MVC)
стал стандартом уже давно.В веб-приложениях он стал использоваться позже, но на
сегодня приобрел широкое распространение.
Схема архитектуры Model-View-Controller (MVC) разделяет приложение на три
основных компонента: модель, представление и контроллер (рис. 2). Платформа MVC
определяется в сборке System.Web.Mvc.
Рис 2.
Шаблон разработки MVC
MVC представляет собой стандартный шаблон разработки, знакомый многим
специалистам. Некоторые типы веб-приложений имеют преимущества при создании на
платформе MVC. Для других может быть целесообразно использование традиционной схемы
приложения ASP.NET, основанной на веб-формах и обратной передаче. В некоторых случаях
возможно сочетание двух подходов: применение одной схемы не исключает использования
другой.
В состав платформы MVC входят следующие компоненты.
 Модели. Объекты моделей являются частями приложения, реализующими логику
для домена данных приложения. Объекты моделей часто получают и сохраняют
состояние модели в базе данных. Например, объект Clientможет получать
информацию из базы данных, работать с ней, а затем записывать обновленные
данные в таблицу Clientбазы данных SQL Server.
В небольших приложениях эта модель подразумевает концептуальное, а не
физическое разделение. Например, если приложение только считывает набор
данных и отправляет его в представление, то физический слой модели и связанных
классов отсутствует. В этом случае набор данных принимает роль объекта модели.
 Представления. Представления
служат
для
отображения
пользовательского
интерфейса приложения. Пользовательский интерфейс обычно создается на основе
данных модели. Примером может служить представление для редактирования
таблицы Client, которое содержит текстовые поля, раскрывающиеся списки и
флажки, значения которых основаны на текущем состоянии объекта Client.
 Контроллеры. Контроллеры осуществляют взаимодействие с пользователем,
работу с моделью, а также выбор представления, отображающего пользовательский
интерфейс. В приложении MVC представления только отображают данные, а
контроллер
обрабатывает
вводимые
данные
и
отвечает
на
действия
пользователя. Например, контроллер может обрабатывать строковые значения
запроса и передавать их в модель, которая может использовать эти значения для
отправки запроса в базу данных.
Шаблон MVC позволяет создавать приложения, различные аспекты которых (логика
ввода, бизнес-логика и логика интерфейса) разделены, но достаточно тесно взаимодействуют
друг
с
другом. Эта
схема
указывает
расположение
каждого
вида
логики
в
приложении. Пользовательский интерфейс располагается в представлении. Логика ввода
располагается в контроллере. Бизнес-логика находится в модели. Это разделение позволяет
работать со сложными структурами при создании приложения, так как обеспечивает
одновременную
реализацию
только
одного
аспекта. Например,
разработчик
может
сконцентрироваться на создании представления отдельно от бизнес-логики.
Связь между основными компонентами приложения
MVC также облегчает
параллельную разработку. Например, один разработчик может создавать представление,
другой — логику контроллера, а третий — бизнес-логику модели.
Создание веб-приложения
Microsoft
разработана
технология
доступа
к
данным
Entity Framework,
спроектированная для того, чтобы удовлетворять требованиям самых разнообразных стилей
разработки.
EntityFramework опирается на концептуальную модель сущностей предметной
области, называемую EntityDataModel (EDM), и выбор того, как создавать эту модель,
является самым первым шагом. Вы можете выбрать один из трех рабочих процессов:
1. DatabaseFirst — вы начинаете с существующей базы данных и используете мастер
для генерации на ее основе концептуальной модели;
2. ModelFirst — вы начинаете с нуля. С помощью визуального дизайнера
(EDMDesigner) проектируется EDM, а затем на ее основе генерируется схема базы
данных;
3. CodeFirst— вы начинаете с классов, которые описывают вашу концептуальную
модель. В этом случае визуальная модель отсутствует.
Так как БД для нашего приложения создана заранее (схема БД представлена на
рис. 3), поэтому выберем подход Database First.
Обратим особое внимание на то, что необходимо изменить тип ключевых полей
таблицы.Теперь у ключейдолжен быть тип uniqueidentifier, а не int, чтобы VSавтоматически
проставила атрибуты Keyключевым полям.
SQLServerManagementStudioнеподдерживаетпрямуюконвертациюintвuniqueidentifier.
Чтобы не пересоздавать базу данных, необходимо сделать следующее:
1. Создать в каждой таблице новое поле с типом uniqueidentifier.
2. Назначить это поле первичным ключом таблицы.
3. Удалить старый первичный ключ.
Основной недостаток этого подхода – утеря всех связей между таблицами внутри БД
(их придется пересоздать).
Рис 3.
Схема БД приложения
Создавать приложение будем в Visual Studio 2012.
Создание проекта
Итак,
создаем
новый
Рис 4.
проект.
Назовем
его
MyMVCApp
(рис. 4).
Создание приложения
Появляется окно, в котором необходимо выбрать тип приложения (выберем
Internet Application), выбрать движок представления (View Engine, выберем Razor), проект
для тестирования создавать не будем (рис. 5).
Рис 5.
Спецификация приложения
Макет веб-приложения готов. Уже можем запустить и посмотреть, что было
сгенерировано Visual Studio.
Добавление модели данных
Теперь добавим в проект модель данных ADO.NETEntityDataModel (рис. 6). Если
этого пункта нет в предлагаемом списке, необходимо выбрать пункт AddNewItem (рис. 7).
Затем в строке поиска вводим название необходимого элемента или его часть, чтобы не
искать нужный элемент вручную, выберем элемент ADO.NETEntityDataModel, назовем нашу
модель данных CompanyDBModel, нажимаем на кнопку Add (рис. 8).
Рис 6.
Рис 7.
Добавление EDM
Добавление нового элемента
Рис 8.
Добавление нового элемента – EDM
На следующем шаге выбираем пункт создать на основе БД (рис. 9).
Рис 9.
Далее появляется окно создания подключения. Выберем NewConnection, чтобы
создать новое подключение.
Рис 10.
Вкачествеисточникаданных
Выбор способа подключения
(DataSource)
выберемMicrosoftSQLи
определим
параметры подключения к нашей базе (рис. 11). Протестируем соединение (TestConnection).
После
получения
сообщения
представлен на рис. 12.
«TestConnectionSucceeded»нажимаем
OK.
Результат
Рис 11.
Задание свойств подключения
Рис 12.
Результат создания подключение
На следующем шаге выберем объекты БД, которые необходимо включить в
модель (рис. 13).
Т.к.
ни
представлений
данных,
StudentMarksDBнет, то в модель включаем только таблицы.
ни
хранимых
процедур
в
Рис 13.
Задание объектов, которые необходимо включить в модель
Созданная модель представлена на рис. 14. Заметим, что кроме таблиц, содержащихся
в БД добавлена служебная таблица sysdiagrams.
Рис 14.
EDM
В проекте появились файл модели и файл БД (рис. 15). Кроме того, в блоге References
появилась сборка Entity Framework.
Рис 15.
Добавленные элементы
Создание приложения
Теперь приступаем непосредственно к созданию веб-приложения. Перед добавлением
нового контроллера необходимо построить решение (BuildSolution). Если этого не сделать,
то классы, сгенерированные EntityFrameworkна основе БД, не будут добавлены в перечень
классов. Добавим новый контроллер (рис. 16).
Рис 16.
Добавление контроллера
Этот
контроллер
будет
предназначен
для
работы
с
таблицей
Students.
НазовемконтроллерStudentsController. ВыберемшаблонMVC controller with read/write actions
and views, using Entity Framework.Выберем класс Client, с которым будет работать
контроллер (если поле выбор недоступно, то нужно сначала скомпилировать проект
[buildsolution]). В поле Datacontextclassвыберем создать новый datacontext (рис. 17). Зададим
имя MyContext и нажмемAdd.В дальнейшем будем использовать созданный сейчасMyContext.
Рис 17.
Задание параметров контроллера ClientsController
Распространённая ошибка на данном выглядит следующим образом (рис. 18):
Рис 18.
Ошибкатипа «No key defined».
Это произошло из-за того, что по какой-то причине ключевые поля таблиц не
получили атрибут [Key] при генерации модели из базы данных. Чтобы от нее избавиться,
необходимо зайти в каждый класс модели (Students.cs, Subjects.cs, StudentsMarks.cs) и
проставить данные атрибуты вручную. Не забудьте включить нужную библиотеку.
usingSystem.ComponentModel.DataAnnotations;
[Key]
publicSystem.GuidStudentID { get; set; }
Естьвозможность, чтопоявилосьнесколькоошибокссообщением «A value of type
'<null>' cannot be used as a default parameter because there are no standard conversions to type».
Для их исправления необходимо в списке входных параметров созданных методов убрать «=
Например,
null».
public ActionResult Details(Guid id
=
null)послеудалениябудемвыглядетьтак: public ActionResult Details(Guid id).
Теперь можем посмотреть, что было сгенерировано VS. Для этого после запуска в
адресную
строку
браузера
http://localhost:53307
добавить
дописать
имя
Students,
представления.
получится
В
нашем
случае
к
http://localhost:53307/Students.
Localhostздесь указывает на то, что сайт размещен на локальном компьютере, 60314 – номер
порта. Видим, что сгенерировано было немало. Мы получили практически готовое
приложение для работы с таблицей Students.
Откроем страницу в PageInspector (рис. 19). Это мощный удобный инструмент для
изучения и создания приложения.
Рис 19.
Открытие Page Inspector
Нажав на Inspect, затем наведя на какой-либо элемент формы, мы видим HTML-код
этого элемента, стиль этого элемента и код этого элемента в Razor-разметке (рис. 20).
Рис 20.
Page Inspector
Нажмем на Inspect, в выделенном абзаце Razor-разметки заменим «CreateNew»на
«Новый студент». Результат представлен на рис. 21.
Рис 21.
Переименование ссылки добавления
Иногда следует заменять не только текстовые аргументы, но и сами элементы, в тех
случаях, когда сгенерированное лямбда-выражение дает нежелательный результат (рис. 22,
23). На рис. 22 показана исходная ситуация, на рис. 23 – результат. Мы заменили элемент с
DisplayNameForна DisplayNameи
лямбда-выражение, находящееся в аргументе метода, на
нужный нам текст.
Рис 22.
Замена DisplayNameFor на DisplayName
Рис 23.
ЗаменаDisplayNameFor на DisplayName
Действуя аналогичным образом, приведем эту (рис. 24) и другие страницы в тот вид, в
котором хотим их видеть. За исключением «шапки», общей для всех страниц, к ней
обратимся позже.
Рис 24.
Результат преобразования интерфейса
Показ изображений
ВклассеPerformerестьполеPerformerPhoto, которое в БД имеет тип image, а в VSтип
byte[]. Если попробуем добавить новую запись в таблицу, то увидим, что нету элемента
управления, позволяющего выбрать файл.
Откроем представление Create.cshtmlдля класса Perfformer. Все элементы управления
располагаются
внутри
проинициализированная
элемента
таким
form
образом, не
Зададимпараметрыформыследующимобразом:
(@using
может
(Html.BeginForm()).
отправлять
файлы
на
Форма,
сервер.
@using (Html.BeginForm("","performer/Create",
FormMethod.Post, new{ enctype = "multipart/form-data" })).По
сути, мы добавили только один
параметр (enctype), т.к. значения по умолчанию остальных параметров совпадают с теми,
которые мы указали. Параметр enctypeотвечает за то, каким образом будут кодироваться
данные. Если необходимо передать файл, то данные не кодируются (значение multipart/formdata).
Добавим лейбл с заголовком и непосредственно элемент управления для выбора
файла:
<label>
Загрузитефайл:
</label>
<divclass="editor-field">
<inputtype="file"name="file"/>
</div>
Изменим метод Createв контроллере: добавим параметр, который будет содержать
загруженный пользователем файл, и реализуем логику преобразования этого файла к
массиву байт. ТеперьметодCreate выглядитследующимобразом:
[HttpPost]
[ValidateAntiForgeryToken]
publicActionResult Create(Performerperformer, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
// Добавлениеидентификатора.
performer.PerformerId = Guid.NewGuid();
// Преобразование файла, загруженного пользователем, к массиву байт.
performer.PerformerPhoto = newbyte[file.ContentLength];
file.InputStream.Read(performer.PerformerPhoto, 0, file.ContentLength);
// Созранение новой записи в БД.
db.Performer.Add(performer);
db.SaveChanges();
returnRedirectToAction("Index");
}
return View(performer);
}
Наша система умеет загружать файла в БД. Теперь необходимо реализовать
отображение этих файлов. Пусть фото сотрудника отображается только при просмотре
подробной информации о нем (представление Details).
Для начала добавим в контроллер новый метод, который будет возвращать фото
конкретного сотрудника (того, информация о котором просматривается в текущий момент).
publicActionResultViewPhoto(Guid id)
{
Performerperformer = db.Performer.Find(id);
if (performer == null)
{
returnHttpNotFound();
}
return File(performer.PerformerPhoto, "image/png");
}
В представление Detailsдобавим необходимые элементы управления. В параметрах
элемента imgукажем, что для получения фото необходимо обратиться к методу ViewPhotoв
контроллере
класса
Performer,и
передадим
idсотрудника,
информация
о
котором
просматривается пользователем.
<divclass="display-field">
@Html.Label("Фото")
<imgsrc="@Url.Action("ViewPhoto", "Performer", new { id=Model.PerformerId
})"width="100"height="100"/>
</div>
Теперь наша система умеет обрабатывать фото сотрудников. Заметим, что сейчас
можно загружать только pngфайлы. Вы можете доработать функционал таким образом,
чтобы можно было загружать любые изображения.
Отображениедаты
При запуске, при попытке создать новый заказ видим, что поле «Дата» отображается
как текстовая строка (рис. 25), хотя имеет тип datetime. Visual Studioгенерирует поле типа
datetimeв стандарте HTML5, но на текущий момент не все браузера полностью
поддерживают этот стандарт. Как текстовая строка это поле отображается во всех браузерах
(были
протестированыInternetExplorer,Google Chrome,
Mozilla Firefox,Yandex)
браузера Opera.Создание заказа в браузере Operaпоказано на рис. 26.
Рис 25.
Создание заказа
кроме
Рис 26.
Создание заказа в браузере Opera
Для того, чтобы во всех браузерах поле «Дата» отображалось корректно, напишем
скрипт. Добавим новый элемент –JavaScript-файл (рис. 28).
Убедитесь, что у вас подключен modernizr (рис. 27). Если такового нет, его
необходимо подключить (скачать можно здесь: http://modernizr.com/).
Рис 27.
Рис 28.
Подключение modernizr.
Добавление JavaScript-файла
Будем использовать jQuery. В открывшемся файлеDataDisplayScript.js напишем:
$(function () {
if (!Modernizr.inputtypes.datetime) {
$("input[type='datetime']").datepicker();
}
});
Тем самым, мы «говорим» браузеру, что если тип элемента datetime, то следует
отобразитьэлемент управления datepicker.
Теперь подключим наш скрипт к файлу Shared/_Layout (рис. 28).
Рис 29.
Расположение файла _Layout
ПодключимкэтомуфайлубиблиотекуjQueryисозданныйскрипт (рис. 29). В названии
файла jqueryуказывается версия библиотеки, посмотреть можно в каталоге Scripts.
<scriptsrc="~/Scripts/jquery-ui-1.8.24.min.js"></script>
<scriptsrc="~/Scripts/DataDisplayScript.js"></script>
Рис 30.
Подключение файла скрипта
Кроме того, необходимо подключить cssдля jQuery (рис. 30):
<linkhref="~/Content/themes/base/jquery-ui.css"rel="stylesheet"/>
Рис 31.
Подключение cssдля jQuery
Теперь, если не браузером не поддерживается datetime, то будет использован
стандартный браузерный элемент управления datepicker.
Теперь
установим
навигацию
в
приложении.
ОткроемвPage Inspectorфайл_Layout.cshtml, показанный на рис. 28. Блок навигации можно
установить в любом месте, мы же оставим в заголовке.
Заменим стандартный блок навигации (рис. 31) своим (рис. 32).
Рис 32.
Стандартный блок навигации
Рис 33.
Измененный блок навигации
Изменим заголовок, напишем там название нашей компании (рис. 33).
Рис 34.
Измененный заголовок сайта
Домашняя страница нам, по сути, не нужна. Роль домашней будет исполнять страница
«Заказы».Установим в свойствах проекта, страницу Ordersв качестве стартовой (рис. 34).
Рис 35.
Установление стартовой страницы
Веб-приложение уже можно считать готовым. Оно представляет собой единую
систему, предназначенную для работой с БД, реализующую основные функции: создание,
добавление, удаление и редактирование записей в БД.
Создание LINQзапроса
Немного усложним наше веб-приложение. Пусть теперь при просмотре подробной
информации о клиенте отображается история его взаимодействия с фирмой XXX, и
подсчитывается общая сумма заказов.
Для реализации запроса воспользуемся LINQ. Выбрать все записи из таблицы Order,
зная Idтекущего клиента можно следующим образом:
from order indb.Order
whereorder.ClientId == id
selectorder;
Эту операцию выбора можно преобразовать влямбда-выражение:
db.Order.Where(item =>item.ClientId == id)
Обе записи дадут один результат. Воспользуемся второй формой записи, изменим
метод Detailsв контроллере Clients. Результат запишем в словарь ViewData – специальную
конструкцию для передачи данных между контроллером и представлением.
publicActionResult Details(Guid id)
{
Clientclient = db.Client.Find(id);
if (client == null)
{
returnHttpNotFound();
}
ViewData["ClientOperations"] = db.Order.Where(item =>item.ClientId == id);
return View(client);
}
ВRazor-разметкеможноиспользоватьHTML-теги.
Преобразуем
код
представления
Clients/Detailsследующим образом.
1. Создадим таблицу, состоящую из 2-х столбцов. В первом оставим то, что
имеется сейчас, во втором будем выводить результаты запроса.
2. Правый столбец разделим на 3 части. В них будем выводить наименование
оказанной услуги, дату обращения и ФИО исполнителя.
В итоге, файл выглядит следующим образом (желтым цветом выделена та часть,
которая уже была):
@model CompanyMvcApp.Models.Client
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
@*Объявляемтаблицу*@
<table>
@*делим таблицу на 2 столбца, равные по ширине*@
<colgroup>
<colwidth="50%"/>
<colwidth="50%"/>
</colgroup>
<tr>
<td>@*Cлева оставляем часть, созданную ранее *@
<fieldset>
<legend>Client</legend>
<divclass="display-label">
@Html.DisplayNameFor(model =>model.ClientName)
</div>
<divclass="display-field">
@Html.DisplayFor(model =>model.ClientName)
</div>
<divclass="display-label">
@Html.DisplayNameFor(model =>model.ClientAddress)
</div>
<divclass="display-field">
@Html.DisplayFor(model =>model.ClientAddress)
</div>
</fieldset>
</td>
<td>
<table>
@*Правыйстолбецделимна 3 части*@
<colgroup>
<colwidth="30%"/>
<colwidth="30%"/>
<colwidth="30%"/>
</colgroup>
@*Объявляем переменную для накопления суммы*@
@{decimalSum = 0;}
@*В цикле перебираем элементы, записанные в ViewData*@
@foreach (var item in (IQueryable<CompanyMvcApp.Models.Order>)ViewData["ClientOperations"])
{
//Накапливаемсумму
Sum += (decimal)item.Service.ServicePrice;
<tr>
<td>
@*Отображаем наименование услуги*@
@Html.DisplayFor(modelItem =>item.Service.ServiceName)
</td>
<td>
@*Отображаемдату*@
@Html.DisplayFor(modelItem =>item.TransactionDate)
</td>
<td>
@*ОтображаемФИОисполнителя*@
@Html.DisplayFor(modelItem =>item.Performer.PerformerName)
</td>
</tr>
}
<tr>
<td>
@Html.Label("Наобщуюсумму")
</td>
<td>
@*Выводим значение общей суммы*@
@Sum
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.ClientId }) |
@Html.ActionLink("Back to List", "Index")
</p>
Создание SQLзапроса
Создадим похожий запрос для сотрудников. Пусть при просмотре подробной
информации
о
сотруднике
отображается
история
операций,
выполненным
этим
сотрудником.
Реализуем запрос с помощью SQL. Для выполнения запроса необходимо задать
подключение к БД (строка подключения берется из конфигурационного файла web.config).
Обратим внимание на то, что web.configдолжен содержать не только строку подключения,
используемую
EntityFramework,
ноидополнительнуюдляподключенияпосредствомSqlConnection:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;attachdbf
ilename=|DataDirectory|\CompanyDB.mdf;integrated security=True;"
providerName="System.Data.SqlClient" />
Изменим метод Detailsв контроллере Performers:
publicActionResult Details(Guid id)
{
Performerperformer = db.Performer.Find(id);
if (performer == null)
{
returnHttpNotFound();
}
// СоздаемподключениекБД.
using (SqlConnection connection =
newSqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionStrin
g))
{
using (SqlDataAdapter adapter = newSqlDataAdapter())
{
// Строка с текстом SQL запроса.
string query = "SELECT ClientName, ServiceName, TransactionDate FROM Performer P JOIN
\"Order\" O ON P.PerformerId = O.PerformerId JOIN Client C ON O.ClientId = C.ClientId JOIN
\"Service\" S ON S.ServiceId = O.ServiceId Where P.PerformerId = @SearchId";
using (SqlCommand command = newSqlCommand(query, connection))
{
command.Parameters.Add(newSqlParameter(
"@SearchId", id));
// Получаемданные
DataSetdataSet = newDataSet();
adapter.SelectCommand = command;
adapter.Fill(dataSet, "ProductResults");
// Передаемданныевпредставлние.
ViewData["PerformerOrders"] = dataSet.Tables[0];
}
}
}
return View(performer);
}
ИзменимпредставлениеDetailsподобно тому, как это делали при реализации запроса
через LINQ, учитывая, что SQLзапрос возвращает объект типа DataTable:
@model CompanyMvcApp.Models.Performer
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<fieldset>
<legend>Performer</legend>
<divclass="display-label">
@Html.DisplayNameFor(model =>model.PerformerName)
</div>
<divclass="display-field">
@Html.DisplayFor(model =>model.PerformerName)
</div>
<divclass="display-field">
@Html.Label("Фото")
<imgsrc="@Url.Action("ViewPhoto", "Performers", new { id=Model.PerformerId
})"width="100"height="100"/>
</div>
</fieldset>
<tableborder="1">
<colgroup>
<colwidth="30%"/>
<colwidth="30%"/>
<colwidth="30%"/>
</colgroup>
@{System.Data.DataTableobjData = (System.Data.DataTable)ViewData["PerformerOrders"];}
@foreach(System.Data.DataRow row inobjData.Rows)
{
<tr>
@foreach (System.Data.DataColumn col inobjData.Columns)
{
<td>
@if (col.Caption == "TransactionDate")
{
stringdateParam = ((System.DateTime)row[col]).Date.ToString("dd-MM-yyyy");
@Html.Label(dateParam)
}
else
{
@Html.DisplayFor(modelItem => row[col])
}
</td>
}
</tr>
}
</table>
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.PerformerId }) |
@Html.ActionLink("Back to List", "Index")
</p>
Наше приложение готово.
Download