Добавление аннотаций данных к унаследованному классу

Скажем, у меня есть следующий класс:

public class ContactUsFormModel : AddressModel
{
    [DisplayName("Title")]
    [StringLength(5)]
    public string Title { get; set; }
    [DisplayName("First name (required)")]

    [Required(ErrorMessage = "Please enter your first name")]
    [StringLength(50, ErrorMessage = "Please limit your first name to {1} characters.")]
    public string FirstName { get; set; }

    // etc...
}

Можно ли добавить обязательный атрибут к свойству класса AddressModel в классе ContactUsFormModel?

Ответ 1

Хорошо. Я нашел обходное решение для этого, добавив новое свойство в класс:

public bool AddressIsRequired { get; set; }

Я мог бы установить это при создании моей модели для разных форм, а затем вместо обычного нормального атрибута я сделал свой собственный валидатор:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public sealed class AddressRequiredAttribute : RequiredAttribute, IClientValidatable
{
    public AddressRequiredAttribute()
        : base()
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        Type addresType = typeof(AddressModel);
        if (context.ObjectType == addresType || context.ObjectType.BaseType == addresType)
        {
            AddressModel baseModel = (AddressModel)context.ObjectInstance;
            if (baseModel != null && baseModel.AddressIsRequired)
            {
                return base.IsValid(value, context);
            }
        }

        return ValidationResult.Success;
    }
}

И затем в моей AddressModel я мог бы отметить мои свойства как таковые:

[AddressRequired(ErrorMessage = "Please enter your Postcode")]
public string Postcode { get; set; }

Я собираюсь оставить это открытым, если кто-то сможет найти лучший способ сделать это (т.е. сможет просто изменить аннотацию данных, не создавая отдельный атрибут). Этот способ делать вещи также означает, что если вы расширяете помощника labelfor и используете метаданные, чтобы проверить флаг IsRequired, свойства, помеченные этим атрибутом, всегда будут отмечены как требуется (я думаю, это может быть потому, что он наследуется от требуемого атрибута)

Ответ 2

Попробуйте использовать MetadatatypeAttribute. Создайте класс seprate для метаданных, в котором вы напрямую добавляете атрибуты в свои свойства.

[MetadataType(typeof(MyModelMetadata ))]
public class ContactUsFormModel : AddressModel
{
    [DisplayName("Title")]
    [StringLength(5)]
    public string Title { get; set; }
    [DisplayName("First name (required)")]

    [Required(ErrorMessage = "Please enter your first name")]
    [StringLength(50, ErrorMessage = "Please limit your first name to {1} characters.")]
    public string FirstName { get; set; }

    // etc...
}

internal class MyModelMetadata {
    [Required]
    public string SomeProperyOfModel { get; set; }
}

[изменить] Вышеуказанный метод вам не подходит, поскольку вы сказали, что он не добавит атрибуты в базовый класс.

Так что сделайте свойства в AddressModel virtual и override их в ContactUsFormModel, и таким образом вы можете добавить атрибут.