dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.2k stars 4.72k forks source link

Unexpected/undocumented Exception in Validator.TryValidateObject #54481

Open Timo-Weike opened 3 years ago

Timo-Weike commented 3 years ago

Description

If you run a program like

using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");

        var instance = new Foo();
        var res = new List<ValidationResult>();
        var b = Validator.TryValidateObject(instance, new ValidationContext(instance), res, true);
    }
}

public class Foo 
{
    public int Id { get; set; }

    [MaxLength(20)]
    public int SomeInt { get; set; }
}

You get an unexpected/undocumented InvalidCastException from the MaxLength attribute on a property which is not supported. However the documentation for the Validator.TryValidateObject does not state that exceptions produced by the Validate calls of the attributes get bubbled up, nor does the documentation for the MaxLength state that this exception will be produced if used on a property that is not of an array-like type.

Also the fact that the exception does not get wrapped up in a ValidationResult does not help in finding the root cause of the problem if a validation attribute is not setup correctly.

I would suggest wrapping any Exception coming from any validation attribute to be wrapped in a ValidationResult with an added property OriginalException set to the caught exception.

Configuration

Just run the above program in e.g. dotnetfiddle with .Net 5

ghost commented 3 years ago

Tagging subscribers to this area: @ajcvickers See info in area-owners.md if you want to be subscribed.

Issue Details
### Description If you have run a program like ~~~ using System; using System.ComponentModel.DataAnnotations; using System.Collections.Generic; public class Program { public static void Main() { Console.WriteLine("Hello World"); var instance = new Foo(); var res = new List(); var b = Validator.TryValidateObject(instance, new ValidationContext(instance), res, true); } } public class Foo { public int Id { get; set; } [MaxLength(20)] public int SomeInt { get; set; } } ~~~ You get an unexpected/undocumented `InvalidCastException` from the `MaxLength` attribute on a property which is not supported. However the documentation for the `Validator.TryValidateObject` does not state that exceptions produced by the `Validate` calls of the attributes get bubble up nor does the documentation for the `MaxLength` state that this exception will be produced if used on a property that is not of type an array-like type. Also the fact that the Exception does not get wrapped up in a `ValidationResult` does not help in finding the root cause of the problem if a validation attribute is not setup correctly. I would suggest wrapping any Exception coming from any validation attribute to be wrapped in a `ValidationResult` with an added property `OriginalException` set to the caught exception. ### Configuration Just run the above program in e.g. [dotnetfiddle](https://dotnetfiddle.net/b6BRpc) with .Net 5
Author: Timo-Weike
Assignees: -
Labels: `area-System.ComponentModel.DataAnnotations`, `untriaged`
Milestone: -
ajcvickers commented 3 years ago

Notes from triage: We agree that fixing the documentation would be useful. We are unlikely to change the exception type, since exceptions are commonly caught in validation code and so this would be a breaking change for existing applications.