3

UPDATE

After some more testing, I found the same code below works fine when posting to a regular Controller. In this case the ModelState has values. The issue remains when posting to an APIController.

I am posting to a Web API Controller via JQuery to update data. The update method is working, however the ModelState is always empty and ModelState.IsValid is always true. (I would like to use the ModelState to perform server-side validation of the model properties)

In my view I am using JQuery to post the new object values:

@model MyProject.mvc.ViewModels.ReportsViewModel

using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myForm" }))
{
   @Html.EditorFor(model => model.Report)

   <button type="submit" onclick="UpdateObject(); return false;">Update</button>
}

<script type="text/javascript">

function UpdateObject() {

    var updatedReport = {
        ID: $("#ID").val(),
        Name: $("#Name").val()
    };

    $.ajax({
        url: "/api/reports/PutReport",
        data: JSON.stringify(updatedReport),
        type: "PUT",
        contentType: "application/json;charset=utf-8"
    });

    return false;
}
</script>

And my Web API method is called to perform the update operation:

public HttpResponseMessage PutReport(Report report)
{
    // report object is properly populated here

    // ModelState has no values and IsValid is always true

    if (ModelState.IsValid)
    {
        // update object
    }
}

Is this the proper way to post to the Web API method? Is there another step required to get the ModelState populated?

Thanks!

Dave
  • 329
  • 2
  • 6
  • 17

1 Answers1

0

try changing you ajax call to look something like this:

$.ajax({
        url: "/api/reports/PutReport",
        data: { report: JSON.stringify(updatedReport) },
        type: "PUT",
        contentType: "application/json;charset=utf-8"
    });

The model state is coming up as valid as you've not posted the data back correctly (would be my assumption). Hopefully correctly naming the data will sort that out.

Henry
  • 2,187
  • 1
  • 15
  • 28
  • I tried changing the ajax call like this, but no luck. This caused the Web API input parameter to be null (it did not map the values) and the ModelState remains with no values. It does seem like this is the issue though. Any other thoughts? It's driving me crazy! – Dave Aug 21 '12 at 15:28
  • Do you have firebug/chrome developer tools and know how to use them? Would it be possible for you to get what data has been sent in the request? If not, add something like: var data = { report: JSON.stringify(updatedReport) }; console.log(data); (Or alert(data) if you dont know how to use the console atall). Also, I take it your sure it needs to be a PUT? Depending on what your doing you may not need to stringify, try it without the JSON.stringify() and see if you have any different results (But still using the { report : updatedReport } so it names it for the mapper to pick up on. – Henry Aug 21 '12 at 16:35
  • Here's the data from Chrome: {"ID":"431","Name":"testing"}. I changed the type to POST for all tests, no luck. Whenever I add the named prefix so the request looks like this: {"report":{"ID":"431","Name":"testing"}}, the input parameter object in the Web API method doesn't have values bound to it's properties. If I try without JSON.stringify(), it posts the values using name value pairs and the input parameter value is null. – Dave Aug 21 '12 at 17:07
  • Strange, ok lets try a different approach then. You can serialize an entire form very easily. var data = $("#myForm").serializeArray(); and then post that. Removing the content type may help for this as it may not conform. – Henry Aug 21 '12 at 18:45
  • I gave that a try, and it posted the name value pairs: ID=431&Name=testing. My input object was properly populated with the values, but ModelState still has no keys or values. I just tried alternatively posting to a regular Controller instead of an ApiController using my original code. It worked, ModelState has values. Is there something special I need to do for this to work with Web API controllers? – Dave Aug 21 '12 at 19:47
  • Well atleast you now have the data going in, very strange its not populating it though. Is it still empty when the model is actually invalid? – Henry Aug 21 '12 at 20:19
  • @henry-gale I did get it working now, it previously was not submitting error conditions because I was attempting to implement a custom validator provider. I am having an issue with that though: [link]http://stackoverflow.com/questions/11785311/server-side-validation-with-custom-dataannotationsmodelvalidatorprovider[/link]. Any advice is greatly appreciated – Dave Aug 22 '12 at 04:51
  • As far as I know the Controller and APIController have separate model binders so it could be that causing the issue. You need to add the custom validator to the relevant model binder. I'm not currently at my PC but this may give you a pointer as to what to look for and I'll have a dig around once I get the chance. – Henry Aug 22 '12 at 12:36
  • @Dave can you share what you did to get it working? I'm having a similar issue with null values coming in for a simple WebApi based controller. – Norman H Sep 18 '12 at 17:26