如何使用Knockout消费ASP.NET WebApi

3

我对knockout和asp.net webapi都很陌生,但我正在努力学习。我似乎缺少了什么,因为我无法执行get(或post、put等)操作...

以下是我的webapi方法:

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);

}

我的 knockout 代码

            <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>

输出了39行空数据,这对我来说没有任何意义。我错过了什么?

我在下面更新了我的答案,以消除问题的真正根源,而不是治疗症状。 - Max Shmelev
2个回答

4
问题在于处理 $.getJSON() 函数的结果。它返回的是一个字符串,而不是 JSON 对象,当你稍后使用 $.map() 时,你正在迭代你字符串的39个字符,而不是你需要的对象。
要解决这个问题,你需要将字符串解析为 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);
});

更新:

我非常感兴趣,为什么您得到一个字符串而不是像$.getJSON()函数应该返回的真实对象。原因是您的WebApi方法。只要它返回一个字符串,WebAPI引擎就会将其额外转换为JSON字符串(它并不关心您已经这样做了)。结果你有两个被JSON化的对象,jQuery无法解析。

您需要在WebAPI方法中返回一个List<Task>而不是一个string,并且不要将其转换为JSON:

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

现在你可以像之前一样留下你的JS代码(不需要额外的parseJSON),因为现在你将得到一个真正的对象。


0
尝试使用ko.mapping插件。它将单个对象放在Knockout喜欢的格式中。
代码应如下所示
    // initial state from server, convert it to Task instances, then populate self.tasks
    $.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) {

                self.tasks = ko.mapping.fromJSON(allData);
    });

尝试过了,但它没有返回数据。嗯。 - user1186651

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接