Итак, все готово к созданию исходного кода на основе заготовок. Установлены требуемые инструменты, отредактированы необходимые файлы. Давайте сгенерируем Контроллеры и Представления.
Возможно у кого-то скажет, что на работу с заготовками ушло много времени и проще все сделать вручную. Здесь необходимо отметить, что создавать или редактировать заготовки приходится не часто. А вот использовать их можно практически в каждом проекте. Создав свой или взяв готовый комплект заготовок можно сильно упростить работу в дальнейшем.
Генерируем исходный код
Для создания исходного кода достаточно воспользоваться командой Scaffold:
PM> Scaffold Controller Tag -DbContextType CatalogContext -Repository -ReferenceScriptLibraries
.........
PM> Scaffold Controller Publisher -DbContextType CatalogContext -Repository -ReferenceScriptLibraries
.........
PM> Scaffold Controller Language -DbContextType CatalogContext -Repository -ReferenceScriptLibraries
.........
PM> Scaffold Controller BookDetails -ControllerName Catalog -DbContextType CatalogContext -Repository -ReferenceScriptLibraries
.........
В результате для каждого класса Модели будут созданы:
- Контроллер, имя которого получено исходя из названия указанного класса Модели. Например, для класса Tag будет сгенерирован TagsController, реализующий Контроллер Tags. В последний будут добавлены следующие Действия:
- Index – для вывода таблицы с записями из базы данных;
- Create – с его помощью можно ввести и сохранить новую запись;
- Edit – предназначено для редактирования информации;
- Delete – служит для удаления выбранной записи (с подтверждением).
- Класс, реализующий репозиторий для взаимодействия с базой данных. Он будет назван исходя из следующего шаблона: <имя класса Модели>Repository. В том же файле расположится описание его интерфейса.
- Для Представлений, необходимых для указанных выше Действий, в папке View будет создана подпапка с именем, аналогичным имени Контроллера.
Обратите внимание, что для класса BookDetails определено свое имя Контроллера – Catalog. Соответственно, его реализация будет размещена в классе CatalogController.
Копируем исходные файлы
При модификации заготовок было решено изменить их пространства имен и, соответственно, место расположение некоторых файлов с исходным кодом. Поэтому в папке Models создадим подпапки:
- Repositories, куда перенесем все файлы с реализацией репозиториев.
- DbContext, где будет расположен контекст базы данных. Кроме того, изменим его пространство имен с BookCatalog.Models на BookCatalog.Models.DbContext.
namespace BookCatalog.Models.DbContext
{
using System.Data.Entity;
public class CatalogContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, add the following
// code to the Application_Start method in your Global.asax file.
// Note: this will destroy and re-create your database with every model change.
//
// System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<BookCatalog.Models.CatalogContext>());
public DbSet<BookCatalog.Models.Tag> Tags { get; set; }
public DbSet<BookCatalog.Models.Publisher> Publishers { get; set; }
public DbSet<BookCatalog.Models.Language> Languages { get; set; }
public DbSet<BookCatalog.Models.BookDetails> BookDetails { get; set; }
}
}
Также можно удалить файлы Details.cshtml в папках представлений, так как соответствующее Действие было удалено из Контроллеров еще в заготовках.
Теперь остается сделать несколько настроек чтобы получить работающее веб-приложение. Обратите внимание, что если бы заготовки уже были готовые, то все свелось бы к 4 шагам:
- Создание проекта;
- Установка инструмента для работы с заготовками (1 команда в консоле NuGet);
- 4 команды Scaffold для создания исходного кода;
- Небольшие изменения в настройках, которые будут рассмотрены ниже.
В результате получается веб-приложение, которое может взаимодействовать с реальной базой данных.
Последние настройки
Контроллер по умолчанию
Давайте заглянем в файл Global.asax и посмотрим на метод RegisterRoutes(). В нем указано, что Контроллером по умолчанию является Home. В разрабатываемом веб-приложении в этой роли будет выступать Catalog. Поэтому просто заменим имя в параметре метода MapRoute():
namespace BookCatalog
{
using System.Web.Mvc;
using System.Web.Routing;
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {
controller = "Catalog",
action = "Index",
id = UrlParameter.Optional
} // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
CSS для таблиц
Это не обязательно, но давайте изменим внешний вид таблиц. По умолчанию в них отсутствует какое-либо оформление и все выглядит достаточно слитно. Поэтому внесем необходимые изменения в css-файл проекта. При этом не будем рассматривать их подробности, так как прямого отношения к ASP.NET MVC это не имеет. Сам css-файл есть в приложенном к этой части исходном коде создаваемого веб-проекта.
Корректировки в классе контекста
Чуть-чуть доработаем класс CatalogContext. В частности:
- добавим директиву using для пространства имен BookCatalog.Models и уберем его упоминания в свойствах.
- С помощью рефакторинга изменим имя свойства BookDetails на более логично Books.
Вывод списка ключевых слов
В Представлении Catalog/Index для каждой книги должен отображаться список присвоенных её ключевых слов. Сейчас этот код выглядит следующим образом:
<td>@item.Tags</td>
Однако необходимо учесть, что item.Tags это коллекция, предоставляющая интерфейс ICollection<T>. В данном случае будет вызван её метод ToString(), который просто вернет имя типа. Это не имеет смысла. Поэтому необходимо организовать вывод списка. А поскольку Razor поддерживает использование C# кода, то это сделать можно следующим образом:
@model IEnumerable<BookCatalog.Models.BookDetails>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>@Html.ActionLink("Create New", "Create")</p>
<table>
<tr>
<th></th>
<th>Title</th>
<th>Author</th>
<th>PublishedAt</th>
<th>Url</th>
<th>Description</th>
<th>Tags</th>
<th>Rating</th>
<th>IsFree</th>
<th>IsVisible</th>
<th>Language</th>
<th>Publisher</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
<td>@item.Title</td>
<td>@item.Author</td>
<td>@String.Format("{0:D}", item.PublishedAt)</td>
<td>@item.Url</td>
<td>@item.Description</td>
<td>@string.Join(", ", item.Tags.Select(tag => tag.Text).ToArray())</td>
<td>@item.Rating</td>
<td>@item.IsFree</td>
<td>@item.IsVisible</td>
<td>@(item.Language == null ? "None" : item.Language.Name)</td>
<td>@(item.Publisher == null ? "None" : item.Publisher.Title)</td>
</tr>
}
</table>
В результате вызова Join() будет создана строка из ключевых слов, разделенных запятой с пробелом.
Кроме того, в первой выделенной строчке изменен формат вывода так, чтобы отображалась только дата публикации. По умолчанию там показываясь еще и время, в чем, для даты публикации книги, нет смысла.
Меню
Для навигации по создаваемому веб-приложению можно самостоятельно вводить ссылки для перехода к нужному Действию определенного Контроллера. Для этого достаточно соблюдать следующий формат:
http://<hostname>/<ControllerName>/<Action>/
Однако использовать меню гораздо удобнее. И для того, чтобы отобразить его на всех страницах, добавим следующий код в шаблон раскладки (файл _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>
<div class="menu">
@Html.ActionLink("Catalog", "Index", "Catalog") |
@Html.ActionLink("Publishers", "Index", "Publishers") |
@Html.ActionLink("Languages", "Index", "Languages") |
@Html.ActionLink("Tags", "Index", "Tags")
</div>
@RenderBody()
</body>
</html>
Метод Html.ActionLink() используются для создания ссылки на указанное Действие (в данном случае всегда Index) выбранного Контроллера.
Настраиваем соединение с базой данных
На начальном этапе в качестве СУБД удобнее всего воспользоваться SQL Server Compact. Поэтому необходимо в корневой папке проекта создать специальную ASP.NET папку под названием App_Data. В ней и будет размещен файл с базой данных. Для этого в Solution Explorer / Solution Navigator в контекстом меню нужно выбрать следующий пункт: Add > Add ASP.NET Folder > App_Data.
Теперь необходимо указать веб-приложению, какую СУБД будем использовать. Для этого в файле Web.config добавим строку соединения (connectionStrings), которая выглядит следующим образом:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="1.0.0.0"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
<connectionStrings>
<add name="CatalogContext"
connectionString="Data source=|DataDirectory|\BooksCatalog.sdf"
providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>
<system.web>
Обратите на следующие моменты:
- секция со строками соединения располагаются внутри секции <configuration>;
- имя строки соединения совпадает с именем класса контекста базы данных CatalogContext;
- connectionString указывает где будет размещен файл с базой данных и его имя;
Запускаем веб-предложение
Все готово. Запустим созданное веб-приложение. В начале будет отображена пустая таблица каталога. Используя меню пройдемся по разделам и посмотрим что в них содержится.
Раздел Tags
Здесь отображается список ключевых слов. Добавим несколько, например: ASP.NET, MVC, C#. Обратите внимание, что есть возможность редактирования и удаления. Кроме того, отображается число книг, которые отмечены тем или иным ключевым словом.
Раздел Languages
В этом разделе укажем пару названий языков: English и Русский.
Раздел Publishers
Этот раздел схож по функциональности с Tags. Здесь для каждого издательства отображается число опубликованных им книг, информация о которых есть в базе данных. Добавим одно любое издательство. Обратите внимание, что здесь нет контроля вводимых значений и ничего не мешает создать пустую запись.
Раздел Catalog
А вот тут все гораздо интереснее. И если в таблице ничего удивительного, то форма добавления информации о книге содержит сюрпризы.
В первую очередь обратите внимание на поле Tags. Используемая заготовка, как и стандартные шаблоны ASP.NET MVC 3, не содержат готового элемента управления для выбора множества значений. А вот для выбора из списка языка книги и издателя используются выпадающие списки. Причем они заполнены значениями из соответствующих таблиц.
Давайте введем данные любой книги, но с обязательным указанием издателя. Теперь, если вернуться в раздел Publishers, то можно обнаружить, что число книг теперь стало равно единице. Кроме того, если удалить из списка языков тот, что был выбран для книги, то и данные о книге книга будут также удалены.
Закроем веб-приложение. Здесь хочется еще раз отметить скорость разработки. При наличии заготовок те��ущая версия веб-приложения создается за считанные минуты.
Если сейчас запустить проект повторно, то можно отметить, что все данные остались как на момент его завершения. Чуть выше была сделана настройка для использоваться SQL Server Compact в качестве СУБД. Но откуда взялась сама база данных? Выясним это чуть позже. А пока посмотрим что необходимо изменить, чтобы получить проект, который будет хорошей основой для изучения ASP.NET MVC 3.
Исходный код проекта (C#, Visual Studio 2010):
mvc3-in-depth-basics-07.zip