0

I have a knockout model that I'm trying to post to an MVC4 controller. A simplified version looks like this:

var ItemModel = function (id, name) {
    var self = this;

    self.id = ko.observable(id);
    self.name = ko.observable(name);
};

var Entry = function () {
    var self = this;

    self.Id = ko.observable();
    self.areas = ko.observableArray([]);
};

var EntryModel = function () {
    var self = this;

    self.entry = new Entry();

    self.save = function () {
        $.post("/Edit", ko.toJS(self.entry), function (data) {
            ...
        })};
    };
};

If I add two areas to my model, like this:

viewModel.entry.areas.push(new ItemModel(1, "A"));
viewModel.entry.areas.push(new ItemModel(2, "B"));

and post it using viewModel.save I get two areas from the model binder, but no data in them (i.e. id = 0, name = "").

After some research I found that I'm posting data like this:

id = 1
name = test
area[0][id] = 1
area[0][name] = "A"
area[1][id] = 2
area[1][name] = "B"

and that MVC expects this:

id = 1
name = test
area[0].id = 1
area[0].name = "A"
area[1].id = 2
area[1].name = "B"

How do I get this posted as expected?

Haas
  • 428
  • 6
  • 12
  • How are you sending the data to the server? jQuery AJAX? XmlHttpRequest? Could you show that code? – PatrickSteele Apr 22 '14 at 02:39
  • I think you might be posting the array incorrectly, I see that you are using jquery to post. Look at the answer for this post: http://stackoverflow.com/questions/12572856/jquery-post-array-asp-net-mvc-4. Try posting data using jquery $.ajax function with dataType and contentType set. Also try setting option traditional to true as well. – milagvoniduak Apr 22 '14 at 02:54
  • @PatrickSteele, the posting code is in the save function on the EntryModel. – Haas Apr 22 '14 at 11:06
  • @MyP3uK, thanks. The question you pointed me to fixes the posting. I'm still trying to understand why my data is getting serialized the way it is (maybe ko.ToJS?) and if there's a way to get this working correctly. – Haas Apr 22 '14 at 11:25
  • Try adding an "alert(ko.toJSON(self.entry))" right before the $.post. This will let you verify you actually have the proper data to send. And have you looked at the data going over the wire using something like Chrome Developer Tools or Fiddler? – PatrickSteele Apr 22 '14 at 11:35
  • @PatrickSteele I can see the data in the tools. I can see it on the controller by inspecting the raw post data. It is there. The only issue is that the binder wants properties to be dotted (data[0].Id) indexed and I'm getting them indexed (data[0][id]. – Haas Apr 22 '14 at 16:17

1 Answers1

0

Your model contains the array so you have to stringify your model and send the resultant string to the controller. You can try this:

var EntryModel = function () {
    var self = this;

    self.entry = new Entry();

    //toJSON function produce the JSON string representing entry model
    var dataToSend = ko.toJSON(self.entry);

    self.save = function () {
        $.post("/Edit", dataToSend, function (data) {
            ...
        })};
    };
};
Gaurav
  • 8,367
  • 14
  • 55
  • 90
  • This will post a string to my controller. It can be worked on and deserialized, but it's not the question I have. – Haas Apr 22 '14 at 11:04
  • @Haas its not a `string`, its a JSON string representing your viewModel. And you do not have to deserialize it, MVC's default model binder will do this job for you. – Gaurav Apr 22 '14 at 11:12
  • I tried it and all I got was an empty view model on the controller. – Haas Apr 22 '14 at 11:32
  • can you post your server side view model code structure ? – Gaurav Apr 22 '14 at 12:29