22

I am trying to figure out how I can send some information from a form to a Web API action. This is the jQuery/AJAX I'm trying to use:

var source = { 
        'ID': 0, 
        'ProductID': $('#ID').val(), 
        'PartNumber': $('#part-number').val(),
        'VendorID': $('#Vendors').val()
    }

    $.ajax({
        type: "POST",
        dataType: "json",
        url: "/api/PartSourceAPI/",
        data: JSON.stringify({ model: source }),
        success: function (data) {
            alert('success');
        },
        error: function (error) {
            jsonValue = jQuery.parseJSON(error.responseText);
            jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
        }
    });

Here is my model

public class PartSourceModel
{
    public int ID { get; set; }
    public int ProductID { get; set; }
    public int VendorID { get; set; }
    public string PartNumber { get; set; }
}

Here is my view

<div id="part-sources">
    @foreach (SmallHorse.ProductSource source in Model.Sources)
    {
        @source.ItemNumber <br />
    }
</div>
<label>Part Number</label>
<input type="text" id="part-number" name="part-number" />

<input type="submit" id="save-source" name="save-source" value="Add" />

Here is my controller action

// POST api/partsourceapi
public void Post(PartSourceModel model)
{
    // currently no values are being passed into model param
}

What am I missing? right now when I debug and step through this when the ajax request hits the controller action there is nothing being passed into the model param.

Cory
  • 658
  • 3
  • 7
  • 19
  • Have you tried without `JSON.stringify`? `data: { model: source }`, or possibly just `data : source` - jQuery handles the conversion for you... – nnnnnn Dec 13 '12 at 23:12
  • Yes, I did try it without JSON.stringify, but that didn't work either. I've tried every possible combination I can think of on the AJAX side, but I'm thinking there is something I'm missing on the controller.. I don't know though, this is purely a guess. – Cory Dec 14 '12 at 00:16
  • When you say "nothing" is being passed into the model param, do you mean instance "model" is null? Or are its values defaults / nulls? What happens if you change your model type to string to get the raw representation, or even remove the input parameter and probe the Request.Content and Request.Headers properties directly to find out what the server is receiving? – Snixtor Dec 14 '12 at 06:56

4 Answers4

30

Try this:

jquery

    $('#save-source').click(function (e) {
        e.preventDefault();
        var source = {
            'ID': 0,
            //'ProductID': $('#ID').val(),
            'PartNumber': $('#part-number').val(),
            //'VendorID': $('#Vendors').val()
        }
        $.ajax({
            type: "POST",
            dataType: "json",
            url: "/api/PartSourceAPI",
            data: source,
            success: function (data) {
                alert(data);
            },
            error: function (error) {
                jsonValue = jQuery.parseJSON(error.responseText);
                //jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
            }
        });
    });

Controller

    public string Post(PartSourceModel model)
    {
        return model.PartNumber;
    }

View

<label>Part Number</label>
<input type="text" id="part-number" name="part-number" />

<input type="submit" id="save-source" name="save-source" value="Add" />

Now when you click 'Add' after you fill out the text box, the controller will spit back out what you wrote in the PartNumber box in an alert.

mnsr
  • 12,337
  • 4
  • 53
  • 79
  • 1
    Thank you! by just changing `data: source` fixed it so it would correctly bind to the 'model' param in the controller. I thought I had to include the name 'model:' in my ajax in order for it to work. Thanks a lot! – Cory Dec 14 '12 at 14:58
  • In the case of complex data format (that cant be deserialize by default) you need to receive the json string on the server side. You answer might work for simple data, but wont work for complex one (which is what im searching for haha). Your answer is good for this guys problem though! – Zwik Apr 09 '14 at 15:14
  • 1
    I found that i had to include `contentType: 'application/json'` in my ajax call. Why doesn't this answer need it? – V Maharajh Jun 30 '15 at 23:42
6

Change:

 data: JSON.stringify({ model: source })

To:

 data: {model: JSON.stringify(source)}

And in your controller you do this:

public void PartSourceAPI(string model)
{
       System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();

   var result = js.Deserialize<PartSourceModel>(model);
}

If the url you use in jquery is /api/PartSourceAPI then the controller name must be api and the action(method) should be PartSourceAPI

Jeroen
  • 4,023
  • 2
  • 24
  • 40
3
var model = JSON.stringify({ 
    'ID': 0, 
    'ProductID': $('#ID').val(), 
    'PartNumber': $('#part-number').val(),
    'VendorID': $('#Vendors').val()
})

$.ajax({
    type: "POST",
    dataType: "json",
    contentType: "application/json",
    url: "/api/PartSourceAPI/",
    data: model,
    success: function (data) {
        alert('success');
    },
    error: function (error) {
        jsonValue = jQuery.parseJSON(error.responseText);
        jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
    }
});

var model = JSON.stringify({      'ID': 0,     ...': 5,      'PartNumber': 6,     'VendorID': 7 }) // output is "{"ID":0,"ProductID":5,"PartNumber":6,"VendorID":7}"

your data is something like this "{"model": "ID":0,"ProductID":6,"PartNumber":7,"VendorID":8}}" web api controller cannot bind it to Your model

Ashot
  • 521
  • 2
  • 6
  • 15
-4

I believe you need quotes around the model:

JSON.stringify({ "model": source })
Andy T
  • 10,223
  • 5
  • 53
  • 95
  • 2
    In an object literal the property names don't need to be quoted if they are numeric literals or valid identifier names. So `{model:source}` is fine. – nnnnnn Dec 13 '12 at 23:19
  • Have you used the browser's debugger tools to check what is being sent to the action method in the request body? – Andy T Dec 13 '12 at 23:29
  • Queti, yes I'm using Fiddler and it says no content was sent with the request – Cory Dec 14 '12 at 00:14
  • I tried using quotes and exactly like you did and it didn't make any difference unfortunately. – Cory Dec 14 '12 at 00:14
  • @nnnnnn It may work without the quotes, but according to json.org it's not a valid syntax. But I doubt that it would cause any trouble, so I guess you're right. – z00l Feb 03 '15 at 12:17
  • 1
    @z00l - You only need the quotes for JSON, which this is not. Object literals and JSON are not the same thing. – nnnnnn Feb 03 '15 at 19:37