2

I'm currently trying to post a JSON object from my view to my controller in an MVC 3 app and I'm expecting the data from the request to bind to the model parameter of my controller action. However, when I inspect the HTTP POST request, it looks like the data is being passed as a query string and I'm unsure why (pretty new to all this).

Here's my POST request:

    $.ajax({
        type: 'POST',
        url: "Test/Add",
        data: { Name: name, Age: age },
        success: function (data) {
            console.log("success");
        },
        error: function (xhr, data, message) {
            console.log(data + ": " + message);
        },
        dataType: "json"
    });

Here's the code from my Controller followed by the code for the model I'm trying to bind to:

    [HttpPost]
    public ActionResult Add(PersonModel person)
    {
        System.Threading.Thread.Sleep(1000);

        return View();
    }

    // person model:
    public class Person {

        public string Name {get;set;}
        public int Age {get;set;}

    }

This is the request from fiddler - I've highlighted the parts I'm unsure about:

enter image description here

I thought content type would be "application/json" and that the data wouldn't look like a query string - I thought it would look something like this:

{
    Name: "James",
    Age: 13
}

Ultimately the problem is that if I stick a breakpoint in my controller action I expect to see a populated Person object but it's always null. If I replace the signature to be something like (object name, object age) then I get values for the parameters (a string array for both - so name is a string array with 1 element which is equal to "James").

Any ideas where I've gone wrong?

Oh and just FYI, I'm not actually 13! Those were the first numbers I mashed.

Thanks!

James

2 Answers 2

2

@David is correct in that you need to set the contentType to 'application/json'. But you also need to send JSON. You are sending an object over. To convert it to JSON use JSON.stringify. I tried sending it over as an object with this contentType setting and received a server error. I actually got it to work correctly without setting the contentType. Even though the request came across as "Name=James&Age=13" MVC was able to convert it into an object. I modified your test to echo back the results as JSON and display them.

Here is the modified Controller

        [HttpPost]
    public string Add(PersonModel person)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string result = serializer.Serialize(person);

        return result;
    }

    // person model:
    public class PersonModel
    {

        public string Name { get; set; }
        public int Age { get; set; }

    }

The modified Javascript and HTML looks like this:

<input id="doAjax" type="button"  value="Send Json..."/>
<br />
Results:<br />
<textarea id="results" cols="30" rows="3"></textarea>
<script type="text/javascript">

 $( document ).ready( function () {
    $( "#doAjax" ).click( sendJson );
} );

function sendJson() {
    var name = "James";
    var age = "13";
    var person = { Name: name, Age: age };
    var personJson = JSON.stringify( person );
    $.ajax( {
        type: 'POST',
        url: "Test/Add",
        data: personJson,
        contentType: 'application/json',
        success: function ( data ) {
            var jsonStr = JSON.stringify( data );
            $( "#results" ).val( jsonStr );
        },
        error: function ( xhr, data, message ) {
            var jsonStr = JSON.stringify( data );
            $( "#results" ).val( jsonStr + ": " + message );
        },
        dataType: "json"
    } );
}

Here are the results of some tests:

data = person; contentType = not set; request = "Name=James&Age=13"; response = "{"Name":"James","Age":13}"

data = personJson; contentType = not set; request = "{"Name":"James","Age":"13"}"; response = "{"Name":null,"Age":0}"

data = person; contentType = 'application/json'; request = "Name=James&Age=13"; response = "System.ArgumentException: Invalid JSON primitive: Name"

data = personJson; contentType = 'application/json'; request = "{"Name":"James","Age":"13"}"; response = "{"Name":"James","Age":"13"}"

Note that when the contentType is not set it defaults to 'application/x-www-form-urlencoded'

Sign up to request clarification or add additional context in comments.

2 Comments

Changed my selected answer as this is a more complete solution with a working example. I had actually got this working myself using @Davids contribution plus a bit more googling, however if I'd of tried this first then I would have got there much faster. Cheers - James
Probably the right choice--Kevin definitely pointed out what I missed regarding the stringification of your JSON payload.
1

The dataType passed to $.ajax is the expected response type. You need to add the contentType to specify the payload type.

$.ajax({
    type: 'POST',
    url: "Test/Add",
    data: { Name: name, Age: age },
    contentType: 'application/json' //*********
    success: function (data) {
        console.log("success");
    },
    error: function (xhr, data, message) {
        console.log(data + ": " + message);
    },
    dataType: "json"
});

Here's the jQuery documentation for .ajax() that indicates the default contentType is 'application/x-www-form-urlencoded'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.