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?
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); }
public class UserCreate { [Required] public string Username { get; set; } [Required] public string Password { get; set; } [Required] public string Name { get; set; } }
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.
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.
AddModelError("Region", "Region is mandatory"); ModelState. IsValid will then return false.
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.
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...
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 { ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With