简体   繁体   中英

C# class property validators knowing about neighboring validators

Given a class with properties, and writing custom validators such as FooExists , I'd like to be able to view neighboring validation decorators within my FooExists functionality. Unless there's a smarter thing I should be doing instead.

I have custom validators I throw on top of properties in a variety of classes. In some cases I pair it with [Required] .

In the scenario where it's not required , I'd like to be able to check that within my overriden IsValid , and handle it differently.

public class ExampleDTO
{
    [Required]
    [FooExists]
    public string Foo { get; set; }

    public string Bar { get; set; }
}

public class AnotherExampleDTO
{
    [FooExists]
    public string Foo { get; set; }

    public bool IsMoo { get; set; }
}

[AttributeUsage(AttributeTargets.Property)]
sealed public class FooExistsAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // ideally I could check if this property is required via [Required]

        // look things up in the database, return true or false
        return true;
    }
}

This reason for all this is, if I make a POST to a controller receiving an ExampleDTO , it will be validated such that Foo exists (Required), and that the value is legal (FooExists). However, if I make a POST to a controller receiving AnotherExampleDTO , and leave out the Foo parameter (because it's not required), I don't want it to fail FooExists . FooExists can check if it's null, but really I want to say "if not required and null, that's fine, return true."

I have toyed around with adding my own Required property, so that I can [FooExists(Required=true)]

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
sealed public class FooExistsAttribute : ValidationAttribute
{
    public bool Required { get; set; }

    public override bool IsValid(object value)
    {
        if (!Required && value == null)
            return true

        // look things up in the database, return true or false
        return true;
    }
}

But this feels wrong, not to mention I lose the free [Required] error message.

I'm also trying to avoid (in this case) inheriting IValidatableObject in my DTO and putting this in the model:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    // I could check all of the class properties in here
}

Short answer: No

Long answer: You could get this behavior with some custom code and reflection, but in the case you have outlined that isn't needed.

The [Required] attribute allows you to specify whether empty/null strings are valid. It also only validates strings. To validate an integer you need Range .

See: RequiredAttribute on MSDN , RangeAttribute on MSDN

From your example, [FooExists] as I said, isn't useful at all because you are working with an integer value. If a field isn't required then there is no need for an attribute at all.

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