5

I annotated my model as this:

public class Instance
{
    [Required]
    public string Name { get; set; }
    public string Description { get; set; }
    [Required]
    public string DBServer { get; set; }
    [Required]
    public string Database { get; set; }
}

In the post method I get a null for the value if nothing was sent but Model.State is true. How can the state be true if nothing was sent? The next problem is that the CreateErrorResponse method throws an exception when I call it (probably because the value was null).

public HttpResponseMessage Post([FromBody]Instance value)
{
    if (value != null && ModelState.IsValid)
    {
        ...
    }
    else
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}

Edit: As it seems I didn't explain it right. I try now with some screenshots.

Case 1 I post a correct value using Fiddle and everything works as expected. ModelState.IsValid is true. Valid parameter

Case 2 I post a value with a missing required field (DBServer) and then again everything works as expected. ModelState.IsValid is false.

Missing required field

Case 3 My question. I send a post request with NO information and ModelState.IsValid is true. This seems very strange and I would like to know the reason. Thank you all for your answers.

enter image description here

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Raul
  • 671
  • 1
  • 7
  • 24
  • Possible duplicate of [ModelState is valid with null model](https://stackoverflow.com/questions/19851352/modelstate-is-valid-with-null-model) – Andriy Tolstoy Sep 04 '17 at 12:55

1 Answers1

5

Try abstracting the ModelState check into a filter. You won't have to check for ModelState every time this way and if there's a problem

This code below comes from a great article on ModelState in WebAPI:

http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.ModelBinding;

namespace MyApi.Filters
{
    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid == false)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        }
    }
}

However, what you need to know is that ModelState only checks internal values, so you need to supply a check to see if the item is null before calling on ModelState.

Check this answer for more details: ModelState.IsValid even when it should not be?

Community
  • 1
  • 1
David East
  • 31,526
  • 6
  • 67
  • 82
  • I don't get this one. If I understand it right the filter will check the model before calling my Post method and set the response to a Bad Request. I wanted to get the call into my Post method, but I thought that ModelState.IsValid would be false if something is wrong with the object passed as parameter. If the caller "forgets" to set the object then the model should not be valid. – Raul Dec 27 '13 at 17:27
  • You would use the ValidateModelAttribute on your Api Controller. Whenever an action is executed, hence OnActionExecuting, this method will fire off with the proper HttpActionContext passed to it. This context will know the ModelState within your post and be able to handle an invalid state. This way you don't need to check for it over and over again. As far as your Validation Issue goes, could your provide what a picture of what the [FromBody] parameter looks like when you're posting? – David East Dec 27 '13 at 17:33
  • I am not passing anything. I test extrem cases using Fiddle to see how my service reacts to it and I don't understand than an empty parameter should be valid. – Raul Dec 27 '13 at 23:44
  • You could be "Under-Posting" which can cause problems with Model State. That's why you need to show the JSON you are posting. Even if you're posting "nothing" it is still something. – David East Dec 28 '13 at 00:09
  • I use Fiddler and I didn't introduce anything into the body, so there is no json to post. The same result was using postman with no body. I just try to understand it. Even "Under posting" should return false for IsValid if the fields were no there. In my case there is nohing (??) – Raul Dec 28 '13 at 10:51
  • Drop a break-point on your controller method. Then hover over the parameter in the method to see the values from the object. Take a screenshot of those values. Also, check my updated answer, you may need to change the content type when posting "nothing". – David East Dec 28 '13 at 17:05
  • The parameter value is as I would expect null and so I cannot hover the values. For me it isn't logical to return true for IsValid if the parameter was empty. Is there any way to tell the validations to treat a null value as an invalid model? – Raul Dec 28 '13 at 19:09
  • Thank you David. As the user nemesv puts it "Whether this is a good or bad design decision that if you validate nothing it will true is a different question...", but at least now I understand it. – Raul Dec 29 '13 at 12:40
  • My apologizes too. I thought this was an "Under Posting" issue at first because I did read this clearly enough. – David East Dec 30 '13 at 22:26