Reputation: 2156
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.
Upvotes: 0
Views: 246
Reputation: 1747
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());
}
}
Upvotes: 0
Reputation: 338148
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
});
}
Upvotes: 1