Prevent inheriting validation attributes in model
Asked Answered
K

2

7

I'm using a base contact model which other custom contact models classes inherit.

public class BaseContactModel
{
    [Required(ErrorMessage = "Firstname is required")]
    public virtual string FirstName { get; set; }
}

The base contact model uses validation attributes to flag a property is required but in some cases I want to override or stop that. Is this going to be possible?

public class ContactModel : BaseContactModel
{
    [NotRequired]
    public override string FirstName { get; set; }
}

I attempted to use a new validation attribute NotRequired to just return true, but appears the attributes are just being stacked up so Required & NotRequired are running and the validation is failing.

On looking for solutions (which I couldn't find) I found that some unrelated attributes have an 'inherited' property, but I don't see this in the native validation attributes in System.ComponentModel.DataAnnotations.

Is this a lost cause? Do I need to roll my own versions which would support disabling inheritance? Any help greatly appreciated.

Keitel answered 8/10, 2012 at 19:56 Comment(0)
K
2

See this below, I've created one class Model that inherits from another BaseModel, used the new keyword then validated one of each instance. From what I can see, they both use the base attributes.

I've added a control class ControlModel for clarity on the validation routine.

class Program
{
    static void Main(string[] args)
    {
        ValidationTest<Model>();
        ValidationTest<BaseModel>();
        ValidationTest<ControlModel>();

        Console.Read();
    }

    private static void WriteAttributeInfo<T>()
    {
        Console.WriteLine(string.Concat(typeof(T), " attributes:"));
        typeof(T).GetProperties().SelectMany(m => m.GetCustomAttributes(true)).Select(a => { Console.WriteLine(a); return a; }).ToList();
    }

    private static void ValidationTest<T>()
    {
        object obj = Activator.CreateInstance<T>();
        Console.WriteLine(string.Concat(typeof(T), " test: isValid = ", Validator.TryValidateObject(obj, new ValidationContext(obj, serviceProvider: null, items: null), new List<ValidationResult>())));
    }
}

class ControlModel
{
    public string FirstName { get; set; }

    public string Email { get; set; }
}

class BaseModel
{
    [RequiredAttribute]
    public virtual string FirstName { get; set; }

    [RequiredAttribute]
    public virtual string Email { get; set; }
}

class Model : BaseModel
{
    public new string FirstName { get; set; }

    public new string Email { get; set; }
}

ConsoleApplication1.Model test: isValid = False

ConsoleApplication1.BaseModel test: isValid = False

ConsoleApplication1.ControlModel test: isValid = True

From this example, it appears you can't override/hide/ignore inherited required validation (haven't tried others yet) attributes.

Keitel answered 10/10, 2012 at 10:11 Comment(2)
I hate answering and accepting my own questions but from the test above, it seems like what the original question asked for, cannot be done.Keitel
Is it really no solution for this?Yashmak
H
0

This may be the case where you actually want a new property

 public class ContactModel : BaseContactModel 
{
        [NotRequired]
        public new string FirstName { get; set; } 
}
Homebody answered 8/10, 2012 at 20:0 Comment(4)
Does this replace the attributes? I've tried using new (with a virtual property) but it still seems to be hitting the validation.Keitel
I've used this strategy a few times in the past. It should be a brand new property, therefore only one validation attribute or the other should fire. Of course it depends how you declare or use your model variable to determine which property is actually used. If it is not working, you may want to post some controller code to see if we can figure out why.Homebody
Thanks for your reply, I'll have another effort this evening and may possibly even try on a site straight out the box.Keitel
See below answer and example - from this, it doesn't look like it's going to play ball :(Keitel

© 2022 - 2024 — McMap. All rights reserved.