1

Trying to populate a table using Knockout.

Controller:

public JsonResult GetAllStudents()
        {
            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(_apiInfo.Urlapi);
                MediaTypeWithQualityHeaderValue contentType =
                    new MediaTypeWithQualityHeaderValue("application/json");
                client.DefaultRequestHeaders.Accept.Add(contentType);
                HttpResponseMessage response = client.GetAsync("/api/students").Result;
                string stringData = response.Content.ReadAsStringAsync().Result;
                if (response.IsSuccessStatusCode)
                {
                    return Json(stringData);
            }
            return null;
        }
    }

View:

<table>
    <thead>
    <tr><th>Last name</th></tr>
    </thead>
    <tbody data-bind="foreach: people">
    <tr>
        <td data-bind="text: $data.lastName"></td>
    </tr>
    </tbody>
</table>

Script:

 function AppViewModel() {
        var self = this;
        self.people = ko.observableArray([]),
            $.ajax({
                type: "GET",
                url: '@Url.Action("GetAllStudents", "Konckout")',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (data) {
                    self.people(data);
                },
                error: function (err) {
                    alert(err.status + " : " + err.statusText);
                }
            });
        }
    ko.applyBindings(new AppViewModel());

I tested the return using alert(data), got the following:

[{"id":1,"lastName":"Alexander"},{"id":1,"lastName":"Mike"}]

However no data is displayed in the table!

hncl
  • 2,295
  • 7
  • 63
  • 129
  • 1
    Out of curiosity, why do you have a controller that calls WebAPI instead of just calling WebAPI from javascript directly? – Paul Abbott Aug 02 '17 at 17:55
  • I am getting the data from another WebAPI service. – hncl Aug 02 '17 at 18:08
  • You've got a typo in your URL value of `Konckout` instead of `Knockout`. Also you cannot use the `@Url....` within a .js file it will not compile. You need to use the appropriate path, `/Knockout/GetAllStudents` – John Pavek Aug 02 '17 at 18:31
  • John, thank you. @Url works, I am getting the data values. – hncl Aug 02 '17 at 18:51

2 Answers2

3

If your alert(data); truly is giving you a result that looks like [{"id":1,"lastName":"Alexander"},{"id":1,"lastName":"Mike"}] then your ajax call might be returning a string instead of json. Try parsing your data before stuffing it into the people object.

self.people(JSON.parse(data));

jsFiddle

If that fixes the problem then I think the real issue is that your controller method is double encoding the data. You're getting a response from an external API that is already JSON, and then re-serializing that response by returning it in a JsonResult. Based on this other SO question you should change the controller method to return a ContentResult instead of JsonResult.

Jason Spake
  • 4,293
  • 2
  • 14
  • 22
  • Works great, thank you for taking the time to provide jsFiddle demo. – hncl Aug 03 '17 at 18:15
  • @hncl Welcome. If this worked you should look deeper into why your ajax method is returning the data as a string instead of json. The JSON.parse is really just a band-aid. – Jason Spake Aug 03 '17 at 18:17
  • @hncl Actually this might help: https://stackoverflow.com/questions/5901411/returning-json-from-a-jsonresult-method-in-mvc-controller – Jason Spake Aug 03 '17 at 18:33
  • Excellent suggestion, using ContentResult worked great. Appreciate your help. – hncl Aug 03 '17 at 19:57
0

The viewModel you're setting on the applyBindings is different from the one you're populating.

You could try something like this:

var data = [];   
var viewModel = {
    people: ko.observableArray(data)
};
ko.applyBindings(viewModel);

And then on the success callback, you could do:

viewModel.people(data);

Also I think you don't need the: self.people = ko.observableArray([]),. Just populate it on the callback of the request.

cristianorbs
  • 670
  • 3
  • 9
  • 16