Как я могу оставаться СУХОЙ с моделями просмотра asp.net mvc и атрибутами аннотации данных?
Как я могу оставаться DRY с помощью моделей представления asp.net mvc и атрибутов аннотации данных (валидация, отображение и моделирование данных) с помощью Asp.Net MVC? Я передал объектам модели, а также модели конкретных действий для просмотра. Я нахожу оба направления, чтобы иметь некоторые проблемы, пытаясь оставаться сухими.
-
Использовать объекты модели в качестве модели вашего представления:. Это прекрасно работает в простых ситуациях и позволяет только писать атрибуты аннотации данных один раз, на каждом объекте модели. Проблема возникает, когда у вас есть сложные представления, для которых требуется несколько типов объектов. Результирующая архитектура модели представления - это путаница использования классов модели представления и реальных классов моделей. Кроме того, этот метод может отображать свойства модели для вашего представления, которое вы не намерены.
-
Использовать уникальный класс модели представления для каждого действия: Класс модели представления содержит только определенные свойства вида, украшенные атрибутами аннотации данных. По моему опыту, этот метод не оказался очень сухим, поскольку атрибуты аннотации данных, как правило, дублируются в классах моделей представлений. Например, модели просмотра "Новое" и "Редактировать" разделяют много, но не все, свойств и аннотаций данных.
Как я могу оставаться DRY с моделями просмотра asp.net mvc и атрибутами аннотации данных?
Ответы
Ответ 1
До сих пор я обнаружил, что использование наследования для объединения общих свойств работает лучше всего. Я использую уникальный класс представления за действие и до сих пор очень доволен решением. Он не решает 100% случаев, но он охватывает большинство и почти устраняет дубликаты атрибутов контракта.
Ответ 2
Хорошим вариантом было бы перейти от DataAnnotations к Fluent Validation.
Он позволяет инкапсулировать общую логику проверки в классе, который вы можете применить позже к своим моделям.
Из документации:
[Validator(typeof(PersonValidator))]
public class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.Id).NotNull();
RuleFor(x => x.Name).Length(0, 10);
RuleFor(x => x.Email).EmailAddress();
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Ответ 3
У меня есть метаданные, определенные в С# следующим образом:
public class Meta
{
public class Client
{
public class Name
{
public const bool Required = true;
public const DataType Type = DataType.Text;
public const int MaxLength = 30;
public const int MinLength = 1;
public const string Regex = @"^[\w\d\.-_]{1,30}$";
}
public class Email
{
public const bool Required = false;
public const DataType Type = DataType.EmailAddress;
public const int MaxLength = 256;
public const int MinLength = 4;
public const string Regex = @"^[email protected]+$";
}
}
}
объявляя их как константы, вы можете использовать DataAnnotations как для BL-объектов, так и для моделей пользовательского интерфейса:
[DataContract]
[Serializable]
public class ClientInfo
{
[DataMember]
[Required(AllowEmptyStrings = !Meta.Client.Name.Required)]
[StringLength(Meta.Client.Name.MaxLength, MinimumLength = Meta.Client.Name.MinLength)]
[RegularExpression(Meta.Client.Name.Regex)]
public string Name { get; set; }
...
}
ну да, вы дублируете атрибуты, но не метаданные! В addtition у меня есть тривиальный препроцессор для генерации sql-скриптов из шаблона (специальная обработка для *.Required и т.д.):
создать таблицу dbo.Client( Имя nvarchar ({# Client.Name.MaxLength}) {# Client.Name.Required}, Электронная почта nvarchar ({# Client.Email.MaxLength}) {# Client.Email.Required},
....
В пользовательском интерфейсе вы можете использовать наследование, чтобы не дублировать свойства. Например, если у вас есть модель с 10 свойствами, но вам нужно отредактировать только 2 из них, создайте EditModel и наследуйте ViewModel от него. Ключ здесь состоит в том, чтобы иметь метаданные в одном хранилище и использовать его как можно больше. Надеюсь, вы получите эту идею.