0

I'm trying to get backbone to do a POST when I call fetch on a model, but nothing I've tried so far seems to work. I also need to pass multiple parameters in the fetch (not just an ID), and need to use jsonp.

I tried overriding the sync method in the model to look like below so that it will do the POST, but it doesn't seem to work (a GET call is still being made).

sync: function(method, model, options) {
      if (method === "read") {
        method = "create";
      }

      return Backbone.sync.call(this, method, model, options);
}

And the fetch looks something like this:

var model = new MyModel();
var deferred = model.fetch({
        dataType: "jsonp",
        data: {
          parm1: "somevalue",
          parm2: false,
          parm3: {
            type1: "abc",
            type2: "123"
          }
        }
});

Any ideas on why this would not be working?

Thanks so much!!

Steve
  • 21
  • 6
  • You shouldn't be trying to turn your fetch into a POST, you should be changing your server to use GET like it should be. – david May 29 '14 at 00:46
  • You cannot POST using JSONP. [See previous accepted answer for more information](http://stackoverflow.com/a/4508215/1723135). – jurassix May 29 '14 at 01:10
  • Ah, thanks for the info and the link!! I didn't know JSONP didn't allow POSTs. – Steve May 29 '14 at 02:37

2 Answers2

2

You can pass type as part of the fetch method options argument. What will happen is that Backbone will sync your request as a read method, which it is, and just before calling jQuery's ajax method it will override the type, as you can see in Backbone's source code.

var xhr = options.xhr = Backbone.ajax(_.extend(params, options));

So your code should look something like that:

var model = new MyModel();
var deferred = model.fetch({
    type: "post",
    dataType: "jsonp",
    data: {
      parm1: "somevalue",
      parm2: false,
      parm3: {
        type1: "abc",
        type2: "123"
      }
    }
});

Remember that the options you pass to the fetch method are basically jQuery's ajax options, with the extension of Backbone's options.

iMoses
  • 4,338
  • 1
  • 24
  • 39
  • For whatever reason, that doesn't seem to be working for me either. Is there a working example of this in JSFiddle somewhere? – Steve May 28 '14 at 23:06
  • It's not the best example ever, but if you open your console then run the script you can see in your network tab that an ajax call was made to `google.com` using `post`. http://jsfiddle.net/mdGva/ – iMoses May 28 '14 at 23:19
  • I'm getting this error: XMLHttpRequest cannot load http://www.google.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access. One thing I noticed when doing the fetch was an issue with the URL. It looks like if the URL is within the current domain, a POST is issued. If it is outside the current domain, even if dataType: 'jsonp' is used, it still seems to issue a GET request. – Steve May 28 '14 at 23:35
  • If you are talking about jsfiddle then it's because they redirect `post` requests to the `echo api` into `get` requests. an example using a url within the domain. works for me, you can see it was a `post` request in the dev-tools. http://jsfiddle.net/mdGva/1/ – iMoses May 28 '14 at 23:40
  • Well, it works when within the local domain, but the first example always does a GET request for an external domain, which unfortunately is what I need to access. – Steve May 28 '14 at 23:56
  • 1
    +1 for teaching me something new about the Backbone source code – cs_stackX May 29 '14 at 01:35
  • Can you provide a jsfiddle of your own So I could examine the problem you are having? – iMoses May 29 '14 at 06:08
0

You need to set the type to "post" in the options that are passed to Backbone.sync. As mentioned in the sync docs, options is "success and error callbacks, and all other jQuery request options":

sync: function(method, model, options) {
  var opts = options;

  if (method === "read") {
    method = "create";
    opts = $.extend({}, opts, {
      type: "post"
    });
  }

  return Backbone.sync.call(this, method, model, opts);
}
Ross Allen
  • 43,772
  • 14
  • 97
  • 95