【问题标题】:Backbone Send Post data encoded as query string骨干网发送 Post 数据编码为查询字符串
【发布时间】:2012-07-10 15:13:48
【问题描述】:

我正在创建一个连接到 RESTful 后端的主干应用程序。当我在模型上调用 save() 时,它会将帖子数据作为字符串化 JSON 发送:

{"firstName":"first","lastName":"last","Email":"email@gmail.com"}

但我的服务器希望它像查询字符串一样格式化:

firstName=first&lastName=last&Email=email@gmail.com

有没有办法让骨干网以不同的方式发送它?

【问题讨论】:

  • 如果这是您的后端所期望的,那么它不是 RESTful。

标签: rest backbone.js http-post url-encoding


【解决方案1】:

Backbone 不提供开箱即用的类似功能。
但是很容易覆盖和自定义它以满足您的需求。

查看源代码: http://documentcloud.github.com/backbone/docs/backbone.html

并检查调用save,它将在后台触发sync 调用。

所以你需要用你自己的覆盖Backbone.sync 函数。

我会修改以下部分:

if (!options.data && model && (method == 'create' || method == 'update')) {
      params.contentType = 'application/json'; 
      params.data = JSON.stringify(model.toJSON());
}

if (!options.data && model && (method == 'create' || method == 'update')) {
      params.contentType = 'application/json';
      params.data = $.param(model); // <-- CHANGED 
}

注意我正在使用jQuery param

如果您想使用自定义函数,请检查以下问题: Query-string encoding of a Javascript Object

[更新。]
不需要直接修改。最好用你自己的函数'Backbone.sync'覆盖它 检查 Backbone 存储库的“TODO”示例。它有一个 localStorage.js 文件覆盖 Backbone.sync 函数 https://github.com/documentcloud/backbone/tree/master/examples

【讨论】:

  • 我想过这样做,但我想避免编辑主干源,我想我可以在我的应用程序启动时将 Backbone.sync 函数替换为修改后的函数,而不是直接编辑主干.js文件。像这样“覆盖”主干方法是否常见?
  • 我只是尝试在我的应用程序加载时覆盖 Backbone.sync 函数,它不起作用,因为同步使用的 methodMap 数组是在 Backbone 模块中本地定义的,所以我的新同步函数没有访问权限给它。要修复此 Id,必须编辑backbone.js 并将其设置在Backbone 对象上,以便我可以在backbone.js 之外引用它:var methodMap=[...]; Backbone.methodMap = methodMap;,所以我不妨在那里更改同步。但我不想碰backbone.js,它似乎是错误的。例如升级骨干网会很困难,必须先找到所有特定领域的代码。
  • 我更新了答案。也许您尝试在加载之前覆盖 Backbone?
  • 如果您实际上并未发送 JSON,则绝对不应继续发送“application/json”标头。正在发送的数据是“application/x-www-form-urlencoded”。
【解决方案2】:

我在工作中遇到了这个问题,Backbone.emulateJSON 也对我不起作用。在一些帮助下,我能够想出这个解决方法。我们覆盖了 Backbone.ajax 函数并将 contentType 更改为“application/x-www-form-urlencoded”并使用 $.param 正确序列化数据。

Backbone.ajax = function() {
    if(arguments[0].data && arguments[0].contentType == "application/json"){
        arguments[0].data = $.param(JSON.parse(arguments[0].data));
        arguments[0].contentType = "application/x-www-form-urlencoded";
    }
    return Backbone.$.ajax.apply(Backbone.$, arguments);
}

【讨论】:

    【解决方案3】:

    也许这可以帮助你,试试: http://backbonejs.org/#Sync-emulateJSON

    【讨论】:

    【解决方案4】:

    我通过覆盖模型的同步函数来做到这一点:

    var MyModel = Backbone.Model.extend({ 
        "sync": function(method, model, options) {
            if (method == "update" || method == "create") {
                options = options ? _.clone(options) : {};
                options['data'] = $.param(this['attributes']);
            }
            var arguments = [method, model, options];
            return Backbone.sync.apply(this, arguments);
        }
    });
    

    【讨论】:

      【解决方案5】:

      我找到解决方案,请参阅:

      1. 我用

        Backbone.emulateJSON = true;

      2. 我写“更新”案例:

        options.url = "/user/"+Math.random(1, 1000);
        options.type = "POST";
        //.1/2 WORK
        //options.data = (model instanceof Backbone.Model)?model.toJSON():{};
        options.data = model.toJSON();
        break;
        

      【讨论】:

        【解决方案6】:

        Backbone.sync 使用jQuery.ajax 函数,因此我们可以修改发送到服务器的jqXHR 或数据(通过beforeSend)。

        var oldSync = Backbone.Model.prototype.sync;
        var SomeModel = Backbone.Model.extend({
            url: 'test.json',
        
            defaults: {
                id: 1,
                foo: 'test'
            },
        
            sync: function (method, model, options) {
                // options are passed to the jQuery.ajax
                _.extend(options, {
                    emulateHTTP: true,
                    emulateJSON: false,
                    beforeSend: function(xhr, settings) {
                        // settings.data is a body of our request.
                        if (_.isString(settings.data)) {
                            // settings.data is a JSON-string like '{"id":1, "foo":"test"}'
                            settings.data = Backbone.$.parseJSON(settings.data);
                        }
        
                        settings.data = Backbone.$.param(settings.data);
                        // settings.data is 'id=1&foo=test'
                    }
                });
        
                oldSync.apply(this, arguments);
            }
        });
        
        var model = new SomeModel();
        model.save();
        

        实际上我们可以创建一个mixin! :)

        【讨论】:

        • 代码只回答are usually frowned upon。尝试添加an explination or code comments。谢谢。
        • 或者,换一种说法:好的答案伴随代码示例,并为未来的读者提供解释。虽然问这个问题的人可能理解你的答案,但解释你是如何得出这个问题的可以帮助无数其他人。
        • 对不起,伙计们。我已经更新了答案。我的英语很差,我知道,但我尽力了:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多