简体   繁体   中英

Adding Data Annotations to Inherited Class

Say I have the following class:

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...
}

Am I able to add a required attribute to a property from the AddressModel class in the ContactUsFormModel class?

Try to Use MetadatatypeAttribute . Create seprate class for metadata where you directly add attributes to your properties.

[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; }
}

[Edit] Above method is not useful for you, as you said it will not add attributes to base class.

So make the properties in AddressModel virtual and override them in ContactUsFormModel and this way you can add attribute.

Ok I have found a workaround to this by adding a new property to the class:

public bool AddressIsRequired { get; set; }

I could set this when building my model for different forms and then instead of using the normal required attribute, I made my own custom validator:

[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;
    }
}

And then in my AddressModel I could mark my properties as such:

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

I am going to leave this open if anyone is able to find a better way of doing this (ie able to just change the data-annotation without having to make a separate attribute). This way of doing things also means that if you extend the labelfor helper and use the metadata to check the IsRequired flag, the properties marked with this attribute will always be marked as required (I think this could be because it inherits from the required attribute)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM