【问题标题】:Issue binding JSONP data with Knockout.js使用 Knockout.js 绑定 JSONP 数据
【发布时间】:2013-01-14 22:10:08
【问题描述】:

我正在处理一个涉及跨域调用的 Web 项目,我决定使用 Knockout.js 和 ASP.NET Web Api。我在 VS 2012 中使用了单页应用程序模板,并按原样实现了 Knockout 类。当我从同一个域进行 JSON 调用时,该页面效果很好,但是当我尝试从远程服务器使用 JSONP 时,敲除似乎没有绑定数据。在进行 JSONP 调用时,我可以看到从远程接收到的 JSON 数据,但是敲除无法绑定数据。

这是我的 JavaScript ViewModel 类:

window.storyApp.storyListViewModel = (function (ko, datacontext) {
    //Data
    var self = this;
    self.storyLists = ko.observableArray();
    self.selectedStory = ko.observable();   
    self.error = ko.observable();

    //Operations
    //Load initial state from the server, convert it to Story instances, then populate self

    datacontext.getStoryLists(storyLists, error); // load update stories      

    self.selectStory = function (s) {
        selectedStory(s); $("#showStoryItem").click(); window.scrollTo(0, 0);
        storyItem = s;        
    }
    //append id to the hash for navigating to anchor tag
    self.backToStory = function () {        
        window.location.hash = storyItem.id;       
    }

    self.loadStories = function () {
        datacontext.getStoryLists(storyLists, error); // load update stories
    }

    return {
        storyLists: self.storyLists,
        error: self.error,        
        selectStory: self.selectStory
    };
})(ko, storyApp.datacontext);

// Initiate the Knockout bindings
ko.applyBindings(window.storyApp.storyListViewModel);

我的 DataContext 类如下:

window.storyApp = window.storyApp || {};

window.storyApp.datacontext = (function (ko) {

    var datacontext = {
        getStoryLists: getStoryLists
    };

    return datacontext;

    function getStoryLists(storyListsObservable, errorObservable) {
        return ajaxRequest("get", storyListUrl())
            .done(getSucceeded)
            .fail(getFailed);

        function getSucceeded(data) {
            var mappedStoryLists = $.map(data, function (list) { return new createStoryList(list); });
            storyListsObservable(mappedStoryLists);
        }

        function getFailed() {
            errorObservable("Error retrieving stories lists.");
        }

        function createStoryList(data) {
            return new datacontext.StoryList(data); // TodoList is injected by model.js
        }
    }

    // Private
    function clearErrorMessage(entity) {
        entity.ErrorMessage(null);
    }

    function ajaxRequest(type, url, data) { // Ajax helper
        var options = {
            dataType: "JSONP",
            contentType: "application/json",
            cache: false,
            type: type,
            data: ko.toJSON(data)
        };
        return $.ajax(url, options);
    }

    // routes
    function storyListUrl(id) {
        return "http://secure.regis.edu/insite_webapi/api/story/" + (id || "");
    }
})(ko);

此页面:http://insite.regis.edu/insite/index.html 对secure.regis.edu 进行跨域调用,但无法正常工作。然而,secure.regis.eduinsite/index.html 上的同一页面进行 JSON 调用就可以了。

我做错了什么?任何帮助将不胜感激。

【问题讨论】:

  • 我在Firebug的getSucceeded和getFailed函数中设置了断点,发现进入getFailed函数。您的 ajax 调用由于某种原因失败,这就是 Knockout 没有绑定任何内容的原因。
  • 在 Fiddler 中监控流量,我可以看到从服务器返回的 JSON,这让我相信 ajax 调用已成功触发。我仍然无法弄清楚问题是什么。
  • 我也很困惑。在 jQuery 代码的深处,它正在生成“错误:未调用 jQuery18209904291128522722_1359607729260”消息。我不明白它是如何工作的,但它显然与 JSONP 和跨域问题有关。

标签: asp.net web knockout.js asp.net-web-api knockout-2.0


【解决方案1】:

感谢那些提供帮助的人。

我设法通过将 WebApiContrib.Formatting.Jsonp 类添加到我的 WebApi 项目中来解决这个问题,如 https://github.com/WebApiContrib/WebApiContrib.Formatting.Jsonp 中所述,并对我的 jQuery Ajax 帮助器类进行如下轻微修改:

function ajaxRequest(type, url, data, callbackWrapper) { // Ajax helper
    var options = {
        dataType: "jsonp",
        crossDomain : true,
        type: type,
        jsonp: "callback",
        jsonpCallback: callbackWrapper,
        data: ko.toJSON(data)
    };   

    return $.ajax(url, options);
}

一切都像魅力一样。

【讨论】:

    【解决方案2】:

    我建议如下:

    创建一个简化的示例(没有 Knockout),它只使用简单的警报式成功和错误回调进行 AJAX 调用。确认它在跨域情况下抛出错误。

    检查以下链接:parsererror after jQuery.ajax request with jsonp content type。如果这还不够,请在 Web(和 StackOverflow)上搜索有关 jQuery JSONP 解析错误和回调的信息。

    如果您仍然卡住,并且您已经完成了 #1 并看到了我期望您会看到的内容,请使用您的简化示例重新编写这篇文章,并删除对 Knockout 的所有引用(在标题、标签中)。我知道 Knockout,但我不知道 JSONP,而知道 JSONP 的人似乎并没有接触到这个,所以我认为这个问题的受众是错误的。更改标题和标签以强调 JSONP/跨域方面可能会为您提供所需的帮助。

    【讨论】:

      猜你喜欢
      • 2014-04-16
      • 2021-08-03
      • 2023-03-15
      • 1970-01-01
      • 2015-02-26
      • 1970-01-01
      • 2012-06-22
      • 2012-06-16
      • 1970-01-01
      相关资源
      最近更新 更多