Основы. Часть 5 – Создаем Модель

Самое время перейти к разработке демонстрационного проекта. Для этого поставим задачу – создать каталог книг. Несмотря на простоту, он послужит хорошим примером для изучения ASP.NET MVC 3.

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

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

Проектируем Модель

Давайте определим набор данных, который будет соответствовать описанию книги в базе данных создаваемого веб-приложения:

  • уникальный код в локальной базе данных (Id);
  • название (Title);
  • автор или авторы (Author);
  • язык, на котором она написана (Language);
  • издатель (Publisher);
  • дата выхода (PublishedAt);
  • ссылка на сайт книги (для бесплатных изданий) или на онлайн-магазин (для коммерческих) (Url);
  • краткое описание (Description);
  • ключевые слова (Tags);
  • рейтинг (Rating);
  • признак того, что книга доступна бесплатно (IsFree);
  • признак того, что запись о книге может быть отображена в каталоге (IsVisible).

Здесь можно отметить три свойства, которые желательно задавать из готового перечня значений: Language, Publisher и Tags. Для хранения из значений разработаем дополнительные классы с соответствующими именами.

В папке Models создадим следующие файлы:

  • Tag.cs – класс для хранения ключевых слов:
namespace BookCatalog.Models
{
    using System.Collections.Generic;

    public class Tag
    {
        public int Id { get; set; }

        public string Text { get; set; }

        public virtual ICollection<BookDetails> Books { get; set; }
    }
}

В данном классе свойство Books предназначено для получения списка книг, которым было присвоено выбранное ключевое слово.

  • Language.cs – класс для хранения названий языков:
namespace BookCatalog.Models
{
    using System.Collections.Generic;

    public class Language
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public virtual ICollection<BookDetails> Books { get; set; }
    }
}
  • Publisher.cs – класс содержащий информацию об издательстве:
namespace BookCatalog.Models
{
    using System.Collections.Generic;

    public class Publisher
    {
        public int Id { get; set; }

        public string Title { get; set; }

        public string Homepage { get; set; }

        public virtual ICollection<BookDetails> Books { get; set; }
    }
}

В данном случае свойство Books, которое возвращает коллекцию книг, выпущенных издательством.

  • BookDetails.cs – класс, содержащий информацию о книге:
namespace BookCatalog.Models
{
    using System;
    using System.Collections.Generic;

    public class BookDetails
    {
        public int Id { get; set; }

        public string Title { get; set; }

        public string Author { get; set; }

        public int LanguageId { get; set; }

        public int? PublisherId { get; set; }

        public DateTime PublishedAt { get; set; }

        public string Url { get; set; }

        public string Description { get; set; }

        public int? Rating { get; set; }

        /// <summary>Gets or sets a value indicating whether 
        /// the book is free (true) or not (false).</summary>
        public bool IsFree { get; set; }

        /// <summary>Gets or sets a value indicating whether 
        /// the book is visible in the catalog (true) or not (false).</summary>
        public bool IsVisible { get; set; }

        public virtual ICollection<Tag> Tags { get; set; }

        public virtual Language Language { get; set; }

        public virtual Publisher Publisher { get; set; }
    }
}

Давайте рассмотрим некоторые свойства отдельно:

  • Для указания языка и издателя используются свойства LanguageId и PublisherId, которые будут содержать идентификаторы из соответствующих списков. Кроме того, для них добавлены “спутники” Language и Publisher указывающие на соответствующие экземпляры данных классов.
  • Свойство PublisherId может принимать значение null, что будет обозначать отсутствие издателя. Это может потребоваться, например, если это книга опубликованная на сайте автора.

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

А что дальше?

Следующим шагом в разработке должно стать создание Контроллеров и Представлений. Для этого можно поступить аналогично рассмотренному в прошлой части варианту и самостоятельно написать весь код. Но это достаточно трудоемкий способ для относительно однообразной работы.

Creating Controller with EF supportДругим вариантом будет использование готовых шаблонов, поставляемых с ASP.NET MVC 3. Для этого необходимо в диалоге создания Контроллера в качестве Template выбрать: Controller with read/write actions and views, using Entity Framework.

В этом случае помощник ASP.NET MVC 3 создаст Представления и Контроллер. В последний будет добавлен исходный код для взаимодействия с базой данных с применением Entity Framework. Рассмотрим работу этой библиотеки позже, а пока просто взглянем на методы полученного в результате класса Контроллера:

//
// GET: /Catalog/Edit/5
 
public ActionResult Edit(int id)
{
    BookDetails bookdetails = db.BookDetails.Find(id);
    ViewBag.LanguageId = new SelectList(db.Languages, "Id", "Name", bookdetails.LanguageId);
    ViewBag.PublisherId = new SelectList(db.Publishers, "Id", "Title", bookdetails.PublisherId);
    return View(bookdetails);
}

//
// POST: /Catalog/Edit/5

[HttpPost]
public ActionResult Edit(BookDetails bookdetails)
{
    if (ModelState.IsValid)
    {
        db.Entry(bookdetails).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.LanguageId = new SelectList(db.Languages, "Id", "Name", bookdetails.LanguageId);
    ViewBag.PublisherId = new SelectList(db.Publishers, "Id", "Title", bookdetails.PublisherId);
    return View(bookdetails);
}

В примере выше представлены два метода, созданные помощником ASP.NET MVC 3 и относящиеся к Действию Edit. Как можно легко заметить, в коде раскрываются детали работы с базой данных и библиотекой Entity Framework. Такой подход может в дальнейшем способствовать переносу логики приложения в Контроллер, что противоречит сути шаблона MVC.

Вполне логично было бы использовать шаблон Repository, подразумевающий более абстрактную работу с источником данных. Конечно, можно все сделать вручную. К счастью, этом случае есть более удобное решение – давайте сократим срок начальной разработки и применим заготовки (scaffolding).


Исходный код проекта (C#, Visual Studio 2010): mvc3-in-depth-basics-05.zip