Основы. Часть 10 – Названия свойств Модели

В прошлой части все текстовые сообщения были вынесены в файлы ресурсов. Теперь разберемся, как назначить необходимые названия для свойства Модели.

Стандартные возможности ASP.NET MVC 3

Давайте еще раз посмотрим, как в Представлении Catalog/_CreateOrEdit организован вывод названий полей формы ввода данных о книге:

.........
<div class="editor-label">
    @Html.LabelFor(model => model.Url)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Url)
    @Html.ValidationMessageFor(model => model.Url)
</div>
.........

Здесь нет строковой константы. Вместо это используется вспомогательный метод LabelFor() класса HtmlHelper. В качестве параметра он получает лямбда-выражение, возвращающее значение нужного свойства. Результатом работы будет создание HTML тега label для соответствующего поля формы. В коде выведенной страницы это будет выглядеть следующим образом:

<div class="editor-label">
    <label for="Url">Url</label>
</div>

Но откуда взялось название и почему оно совпадает с именем свойства? Метод LabelFor() пытается получить необходимый текст из метаданных класса Модели. А при отсутствии в них необходимой информации использует имена свойств.

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

В исходном коде приложения метаданные можно задать при помощи атрибутов. На этапе выполнения, взаимодействие с ними осуществляется при помощи методов отражения (reflection).

Вернемся к Модели. Во многих случаях нет смысла использовать имя свойства в качестве названия для поля ввода. Поэтому в ASP.NET MVC реализована возможность задать этот текст при помощи атрибута [DisplayName]. Тогда объявление свойства в классе Модели будет выглядеть следующим образом:

[DisplayName("Website")]
public string Url{ get; set; }

Если теперь запустить веб-приложение, то в форме создания профиля для поля Url будет выведен текст "Website". Это уже лучше, но не решает проблему жестко заданных строк, т.к. данный атрибут не позволяет указывать строки из ресурсов.

До выхода .NET 4, решением данной проблемы было создание своей реализации, используя[DisplayName] в качестве базового класса. Но теперь есть возможность использовать стандартный вариант.

Новый атрибут [Display] более универсален. Кроме имени, он может задать в метаданных объекта такие параметры как его описание, краткое имя, подсказку, порядок при выводе в качестве колонок таблицы и ряд других. В контексте решаемой задачи интересны его следующие свойства:

  • Name – имя для отображения в пользовательском интерфейсе;
  • ResourceType – тип ресурса, из которого необходимо загружать текстовые строки.

Необходимо отметить правило установки значений свойств данного атрибута. Если не указано имя типа ресурса ResourceType, то они воспринимаются как обычные строки. В противном случае – как имена строк в заданном ресурсе.

Для использования [Display] необходимо подключить пространство имен System.ComponentModel.DataAnnotations. Тогда объявление свойства примет следующий вид:

[Display(Name = "Url", ResourceType = typeof(BookDetailsRes))]
public string Url { get; set; }

Изменяем классы Модели

В прошлой части все необходимые строки были добавлены в ресурсы. Поэтому остается только присвоить [Display] всем свойствам Модели за исключением тех, которые в принципе не предназначены для отображения. В частности это Id у всех классов, а также LanguageId, PublisherId в BookDetails.

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

  • Класс BookDetails
namespace BookCatalog.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using BookCatalog.Resources.Models;

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

        [Display(Name = "Title", ResourceType = typeof(BookDetailsRes))]
        public string Title { get; set; }

        [Display(Name = "Author", ResourceType = typeof(BookDetailsRes))]
        public string Author { get; set; }

        public int LanguageId { get; set; }

        public int? PublisherId { get; set; }

        [Display(Name = "PublishedAt", ResourceType = typeof(BookDetailsRes))]
        public DateTime PublishedAt { get; set; }

        [Display(Name = "Url", ResourceType = typeof(BookDetailsRes))]
        public string Url { get; set; }

        [Display(Name = "Description", ResourceType = typeof(BookDetailsRes))]
        public string Description { get; set; }

        [Display(Name = "Rating", ResourceType = typeof(BookDetailsRes))]
        public int? Rating { get; set; }

        /// <summary>Gets or sets a value indicating whether 
        /// the book is free (true) or not (false).</summary>
        [Display(Name = "IsFree", ResourceType = typeof(BookDetailsRes))]
        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>
        [Display(Name = "IsVisible", ResourceType = typeof(BookDetailsRes))]
        public bool IsVisible { get; set; }

        [Display(Name = "Tags", ResourceType = typeof(BookDetailsRes))]
        public virtual ICollection<Tag> Tags { get; set; }

        [Display(Name = "Language", ResourceType = typeof(BookDetailsRes))]
        public virtual Language Language { get; set; }

        [Display(Name = "Publisher", ResourceType = typeof(BookDetailsRes))]
        public virtual Publisher Publisher { get; set; }
    }
}
  • Класс Language
namespace BookCatalog.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using BookCatalog.Resources.Models;

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

        [Display(Name = "Name", ResourceType = typeof(LanguageRes))]
        public string Name { get; set; }

        [Display(Name = "Books", ResourceType = typeof(LanguageRes))]
        public virtual ICollection<BookDetails> Books { get; set; }
    }
}
  • Класс Publisher
namespace BookCatalog.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using BookCatalog.Resources.Models;

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

        [Display(Name = "Title", ResourceType = typeof(PublisherRes))]
        public string Title { get; set; }

        [Display(Name = "Homepage", ResourceType = typeof(PublisherRes))]
        public string Homepage { get; set; }

        [Display(Name = "Books", ResourceType = typeof(PublisherRes))]
        public virtual ICollection<BookDetails> Books { get; set; }
    }
}
  • Класс Tag
namespace BookCatalog.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using BookCatalog.Resources.Models;

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

        [Display(Name = "Text", ResourceType = typeof(TagRes))]
        public string Text { get; set; }

        [Display(Name = "Books", ResourceType = typeof(TagRes))]
        public virtual ICollection<BookDetails> Books { get; set; }
    }
}

Если теперь запустить проект, то можно увидеть обновленные подписи элементов формы.

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


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

Комментарии (4) -

Андрей 27.06.2011 0:45:16

Unable to find the requested .Net Framework Data Provider.  It may not be installed. - Скажите пожалуйста что это может быть, - собственно из примера скачанного при запуске двыдает эксэпшн

А Microsoft SQL Server Compact 4.0 установлен?
www.microsoft.com/.../details.aspx

То есть по сути мы можем создать и различные файлы ресурсов для заголовка таблиц (например ТУТ АВТОРЫ) и меток в форме ввода (например ВВЕДИТЕ АВТОРА).

@ Andriy: Не совсем понял вопрос и вопрос ли это?

Добавить комментарий