How to consume asp.net webapi with knockout

asp.net, asp.net-web-api, knockout.js

Solution

The problem is in the handling results of the `$.getJSON()` function. It returns you a string, not a JSON object, and when you do `$.map()` later you're iterating 39 characters of your string, but not the objects you need.

To fix it you need to parse your string as a JSON:

$.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) {
    allData = $.parseJSON(allData);
    var mappedTasks =  $.map(allData, function (item) { return new Task(item) });
    self.tasks(mappedTasks);
});

Update:

I was really interested, why do you get a string instead of a real object as you should get in case of `$.getJSON()` function. And the reason is your WebApi method. As far as it returns a string, WebAPI engine converts it additionally to a JSON string (it doesn't care that you've already done it). As a result you have twice JSONified object and jQuery can't parse it.

All you need to do is to return not a `string` but a `List<Task>` in your WebAPI method and not to JSON it:

public List<Task> GetAllData()
{
    List<Task> llistTask = new  List<Task>();
    ...
    return llistTask;
}

And you can leave your JS code as you had it (no additional `parseJSON`), because now you'll get a real object.

Problem

I am new to knockout and asp.net webapi, but I am trying to learn. I am missing something, as i cannot perform a get(or a post,put...) here is my webapi method ``` public string GetAllData() { List<Task> llistTask = new List<Task>(); Task lobjTask = new Task(); lobjTask.title = "some title"; lobjTask.isDone = false; llistTask.Add(lobjTask); return Newtonsoft.Json.JsonConvert.SerializeObject(llistTask); } ``` my knockout code ``` <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="Scripts/knockout-2.2.0.js"></script> <script src="Scripts/jquery-1.8.2.min.js"></script> </head> <body> <h3>Tasks</h3> <form data-bind="submit: addTask"> Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" /> <button type="submit">Add</button> </form> <ul data-bind="foreach: tasks, visible: tasks().length > 0"> <li> <input type="checkbox" data-bind="checked: isDone" /> <input data-bind="value: title" /> <%-- <a href="#" data-bind="click: $parent.removeTask">Delete</a>--%> </li> </ul> You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s) <span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span> <script type="text/javascript"> function Task(data) { this.title = ko.observable(data.title); this.isDone = ko.observable(data.isDone); } function TaskListViewModel() { // Data var self = this; self.tasks = ko.observableArray([]); self.newTaskText = ko.observable(); self.incompleteTasks = ko.computed(function () { return ko.utils.arrayFilter(self.tasks(), function (task) { return !task.isDone() }); }); // Operations self.addTask = function () { self.tasks.push(new Task({ title: this.newTaskText() })); self.newTaskText(""); }; self.removeTask = function (task) { self.tasks.remove(task) }; // Load initial state from server, convert it to Task instances, then populate self.tasks $.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) { var mappedTasks = $.map(allData, function (item) { return new Task(item) }); self.tasks(mappedTasks); }); } ko.applyBindings(new TaskListViewModel()); </script> </body> </html> ``` The output is 39 rows of null data, which doesnt make sense to me. what am i missing?

Original source