0

I have these classes:

public class RequestModel
{
    [Required]
    public string name { get; set; }
    [Required]
    public List<AnotherClass> anotherClassList { get; set; }
}

public class AnotherClass
{
    [Required]
    public string anotherName { get; set; }
    [Required]
    public List<ThirdClass> third { get; set; }
}

public class ThirdClass
{
    [Required] public string foo3;

    [Required]
    public FourthClass four;
}

public class FourthClass
{
    [Required]
    public string foo4 { get; set; }
    [Required]
    public string bar4

And this controller

public async Task<IActionResult> ValidateModelProperly([FromBody] RequestModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
     return NoContent();
}

And only the [Required] properties from RequestModel and AnotherClass is validated by the framework. The two remaining classes are completely ignored (properties just set to null if i omit them from the json body).

Is there some limitation by the framework, or what the heck is happening?

3 Answers 3

2

Apparently the validation module needs getter and setter methods to be able to validate the requirements. After adding get; set; methods for the properties, the validation works as expected.

Sign up to request clarification or add additional context in comments.

Comments

0

Please see Martin's solution below. My attempts to find a solution were wrong.

EDIT

I had misunderstood your problem at first. This seems to have to do with the validation depth.

Have you tried setting the MvcOptions.MaxValidationDepth Property in your mvc options to null to disable a maximum depth? I'm not sure it will work but it might. You set it in your Startup.cs file like so:

services.AddMvc(options => 
    {
        options.MaxValidationDepth = null;
    })

EDIT

As far as I can tell you need to add BindRequired to the frombody attribute to actually get it to behave as you expect. This results in a method that looks like this:

public async Task<IActionResult> ValidateModelProperly([BindRequired, FromBody] RequestModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
     return NoContent();
}

as opposed to:

public async Task<IActionResult> ValidateModelProperly([FromBody] RequestModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
     return NoContent();
}

I hope this helps, if I misunderstood anything or if you see mistakes I made please let me know!

3 Comments

As the 2 of the classes properties are already validated, and the two last are ignored, i doubt it's gonna change much. But i'm gonna give it a shot :). Edit: Nope, doesn't change a thing.
Ah I can see that I definitely misunderstood your problem!
I figured it out. The [Required] properties needs get and set methods to be able to be validated. I guess the model deserialization is done with reflection or something, and validation is done through getters and setters.
0

With this complicated model, I would recommend to use IValidatableObject or FluentValiation

IValidatableObject use:

public class AnotherClass : IValidatableObject
{
    [Required]
    public string anotherName { get; set; }
    [Required]
    public List<ThirdClass> third { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (third.Any(x => string.IsNullOrWhiteSpace(x.foo3)
                        || string.IsNullOrWhiteSpace(x.four?.foo4)
                        || string.IsNullOrWhiteSpace(x.four?.bar4)))
        {
            yield return new ValidationResult("Invalid");
        }

    }
}

Refer this link if you wanna user FluentValidation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.