Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelState.IsValid even when it should not be?

I have API where I need to validate my user model. I choose an approach where I create different classes for Create/Edit actions to avoid mass-assignment and divide validation and actual model apart.

I don't know why but ModelState.IsValid returns true even when it should not. Am I doing something wrong?

Controller

public HttpResponseMessage Post(UserCreate user) {     if (ModelState.IsValid) // It's valid even when user = null     {         var newUser = new User         {             Username = user.Username,             Password = user.Password,             Name = user.Name         };         _db.Users.Add(newUser);         _db.SaveChanges();         return Request.CreateResponse(HttpStatusCode.Created, new { newUser.Id, newUser.Username, newUser.Name });     }     return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); } 

Model

public class UserCreate {     [Required]     public string Username { get; set; }     [Required]     public string Password { get; set; }     [Required]     public string Name { get; set; } } 

Debug proof

proof

like image 545
Stan Avatar asked Jul 29 '13 12:07

Stan


People also ask

Why is my ModelState IsValid false?

IsValid is false now. That's because an error exists; ModelState. IsValid is false if any of the properties submitted have any error messages attached to them. What all of this means is that by setting up the validation in this manner, we allow MVC to just work the way it was designed.

Which of the following is true about ModelState IsValid?

The IsValid property will be true if the values were able to bind correctly to the model AND no validation rules were broken in the process. It's worth bearing in mind that the value types of the properties of your model will also be validated.

How do you make a ModelState IsValid false?

AddModelError("Region", "Region is mandatory"); ModelState. IsValid will then return false.

How do I know if my ModelState is valid?

Below the Form, the ModelState. IsValid property is checked and if the Model is valid, then the value if the ViewBag object is displayed using Razor syntax in ASP.Net MVC.


2 Answers

The ModelState.IsValid internally checks the Values.All(modelState => modelState.Errors.Count == 0) expression.

Because there was no input the Values collection will be empty so ModelState.IsValid will be true.

So you need to explicitly handle this case with:

if (user != null && ModelState.IsValid) {  } 

Whether this is a good or bad design decision that if you validate nothing it will true is a different question...

like image 120
nemesv Avatar answered Sep 18 '22 15:09

nemesv


Here is an action filter to check for null models or invalid models. (so you dont have to write the check on every action)

using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters;  namespace Studio.Lms.TrackingServices.Filters {     public class ValidateViewModelAttribute : ActionFilterAttribute     {         public override void OnActionExecuting(HttpActionContext actionContext)         {             if (actionContext.ActionArguments.Any(kv => kv.Value == null)) {                 actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Arguments cannot be null");             }              if (actionContext.ModelState.IsValid == false) {                 actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);             }         }     } } 

You can register it globally:

config.Filters.Add(new ValidateViewModelAttribute()); 

Or use it on demand on classes/actions

 [ValidateViewModel]  public class UsersController : ApiController  { ... 
like image 38
Jose Ch. Avatar answered Sep 18 '22 15:09

Jose Ch.