0

I have a controller action where I'm trying to post a model from knockout:

    [HttpPost]
    public void AddItems(MyViewModel model)
    {
        [...]
    }

knockout action:

self.AddItems = function (data, event) {
    var url = "/MyController/AddItems";
    var target = event.target || event.srcElement;
    var model = ko.toJSON(self);
    $.post(url,
            model,
            function (result) {

            })
        .success(function () { console.log("AddItems second success"); })
        .error(function () { console.log("AddItems error"); })
        .complete(function () { console.log("AddItems complete"); });

    // this doesn't work either
    //var model2 = ko.toJSON({ model: self });
    //$.ajax(url, {
    //    data: model,
    //    type: "post",
    //    async: false,
    //    contentType: "application/json",
    //    success: function (data) {
    //        console.log("AddItems second success");
    //    },
    //    error: function (xmlHttpRequest, textStatus, errorThrown) {
    //        console.log("AddItems error");
    //    }
    //});
}

I have commented out another post action which I tried as well - this one doesn't reach the controller action at all returning a 500 error in js console.

The model:

public class MyViewModel
{
    public int Id { get; set; }

    public string Ref { get; set; }

    public List<ItemViewModel> Items { get; set; }

    public decimal PriceTotal { get; set; }
}

The model which gets posted to action has the correct structure but all properties are either empty or null.

How to pass a knockout viewmodel to the action with correct object data?

***** EDIT *****

I think the action doesn't get the json model.

Because when I pass a hand written raw object model:

var model4 = {
  "Ref": "sgsgsasg",
  "Id": 1,
  "PriceTotal": 382
}

it gets to the action nicely and with correct values.

While the knockout passes json and then the action cannot convert it to the mvc model.

nickornotto
  • 1,466
  • 2
  • 29
  • 55
  • I used this example http://www.c-sharpcorner.com/UploadFile/5ff76e/posting-data-to-mvc-action-using-knockoutjs/ to deserialize model from json and used `{ model: ko.toJSON(self) }` to pass it into the action – nickornotto Jul 06 '17 at 15:53

2 Answers2

1

I am pretty sure you are only missing a content type header.

By default jQuery posts data as application/x-www-form-urlencoded. You want application/json. jQuery $.ajax() lets you configure the content type:

self.AddItems = function () {
    return $.ajax({
        url: "/MyController/AddItems",
        data: ko.toJSON(self),
        contentType: "application/json"
    })
    .done(function () { console.log("AddItems success"); })
    .fail(function () { console.log("AddItems error"); })
    .always(function () { console.log("AddItems complete"); });
}

Side note: Returning the request from the function enables you to attach more behavior to it elsewhere:

self.something = function () {
    // do some work on the viewmodel
    self.AddItems().done(function () {
        // we are done
    });
}
Tomalak
  • 306,836
  • 62
  • 485
  • 598
0

You haven't passed the parameter your url is expecting, hence the 500.

self.AddItems = function (data, event) {
    var url = "/MyController/AddItems";
    var target = event.target || event.srcElement;
    $.ajax(url , {
       type: "POST",
       cache: false,
       data: { model: ko.toJSON(self) }
    }).done(function () {
       console.log("AddItems second success");
    }).fail(function (jqXHR, textStatus, errorThrown) {
       console.log("AddItems complete");
    });
}

Controller

[HttpPost]
public void AddItems(string model)
{
    var audit = InsertAudit();
    try
    {
        MyViewModel data = JsonConvert.DeserializeObject<MyViewModel>(model);
        //Logic here
    }
    catch (Exception ex)
    {
         FailAudit(audit.ID, ex.ToString());
    }
}
tyler_mitchell
  • 1,709
  • 1
  • 17
  • 26
  • its not getting deserialised correctly then, see edit, i actually prefer this way as you can can audit data before deserialisation and therefore if it falls over you can catch the exception and log it so no loss of data. – tyler_mitchell Jul 06 '17 at 15:23
  • this hits the action but the model object comes null – nickornotto Jul 06 '17 at 15:24