NancyFx / Nancy

Lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono
http://nancyfx.org
MIT License
7.15k stars 1.46k forks source link

DataAnnotations validation does not validate properties with annotated properties of their own #1155

Open Entroper opened 11 years ago

Entroper commented 11 years ago

If I have a DTO that contains other objects, I would like to add validation attributes to the properties on those objects, and have them be validated on BindAndValidate. Example:

public class VideoProfileContent
{
    [Required]
    public string Name { get; set; }
    public VideoProfile VideoProfile { get; set; }
    public AudioProfile AudioProfile { get; set; }
}

public class VideoProfile
{
    public VideoFormatType FormatType { get; private set; }
    [Range(320, 4096)]
    public int Width { get; private set; }
    [Range(240, 3072)]
    public int Height { get; private set; }
    [Range(5, 144)]
    public double Framerate { get; private set; }
    [Range(100, 10000)]
    public int BitrateKbps { get; private set; }
}

// etc.

The VideoProfileContent.Name property is correctly validated, but none of the VideoProfile properties are validated.

asbjornu commented 8 years ago

This is the default behavior of the System.ComponentModel.DataAnnotations.Validator.TryValidateObject() method. As stated in the documentation:

This method evaluates each ValidationAttribute instance that is attached to the object type. It also checks whether each property that is marked with RequiredAttribute is provided. It does not recursively validate the property values of the object.

(Emphasis mine). There are, however, quite a few workarounds available. Here's a first and second solution based on creating your own [ValidateObject] attribute that you can decorate your objects with, and here's one with a custom implementation of IDataAnnotationsValidator. Afaict, Nancy should be compatible with both solutions.

asbjornu commented 7 years ago

I've outlined the start of a possible solution in this gist. It currently fails with an ArgumentException: An item with the same key has already been added within the CompositeValidator.Validate() method, when it is trying to build a dictionary out of the ModelValidationError objects. Since I don't get any indication for which key is duplicate, this is really hard to debug, so I'm currently stuck.