Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelState is always considered valid, regardless of null values in required fields

I've been looking around and I think my solution is just fine but somehow the ModelState.IsValid property is always true.

Consider the following code snippets:

[Route("address")]
[HttpPut]
[ResponseType(typeof(UserViewModel))]
public IHttpActionResult UpdateAddress([FromBody] UpdateAdressValidationModel model)
{
   if (!ModelState.IsValid)
   {
       return BadRequest(ModelState);
   }
   // irrelevant code omitted
}

[TestMethod]
public void UpdateAddress_WithoutStreet_ReturnsHttpCode400()
{
    var userController = new UserController(new UserRepository(_context));
    var addressInfo = new UpdateAdressValidationModel
    {
        City = "Ghent",
    };

    var response = userController.UpdateAddress(addressInfo) as BadRequestResult;

    Assert.IsNotNull(response);
}

public class UpdateAdressValidationModel
{
    [Required]
    public string Street { get; set; }

    [Required]
    public int? Number { get; set; }

    [Required]
    public string Bus { get; set; }

    [Required]
    public int? PostalCode { get; set; }

    [Required]
    public string City { get; set; }
}

Still gives me a valid modelstate, even though it clearly shows that the required properties are null.

enter image description here

What am I overlooking?

Note that manually adding

Validator.ValidateObject(model, new ValidationContext(model));

at the top of the UpdateAddress method throws a ValidationException on the Street field so it can in fact validate the model. Question remains: why doesn't it automatically?

Furthermore, this isn't applicable because my model isn't null.

like image 807
Jeroen Vannevel Avatar asked Nov 05 '14 16:11

Jeroen Vannevel


1 Answers

Turns out that this answer had the right idea but the solution didn't quite fit.

Validation happens when the posted data is bound to the view model. The view model is then passed into the controller. You are skipping part 1 and passing a view model straight into a controller.

Which is correct, but the proposed solution throws a ValidationException instead of simply setting the IsValid property to false.

Luckily, there is a specific method that can do this: ApiController.Validate(). By adding these lines to my Unit Test it sets the ModelState to invalid and does not throw an exception.

userController.Configuration = new HttpConfiguration();
userController.Validate(addressInfo);
like image 186
Jeroen Vannevel Avatar answered Oct 06 '22 10:10

Jeroen Vannevel