Search code examples
jqueryajaxbackbone.jsasmxmarionette

jquery ajax failing due to options.data being undefined for Backbone.js collections


I'm trying to get some data back from my .asmx web method but it's failing at the ajax call. Here is some of my JS code:

    // BaseCompositeView is basically an object extended from Marionette.CompositeView
    MyListView = App.Base.Objects.BaseCompositeView.extend({
        // contents removed for brevity
    });

    // BaseModel is basically an object extended from Backbone.Model
    MyListView.Model = App.Base.Objects.BaseModel.extend({
        // nothing here
    });

    // BaseCollection is basically an object extended from Backbone.Collection
    MyListView.Collection = App.Base.Objects.BaseCollection.extend({
        url: "../WebServices/MyService.asmx/GetUsers",

        model: MyListView.Model,

        initialize: function(options) {
            this.options = _.extend({}, this.defaults, this.options);

            this.options.data = JSON.stringify({
                "groupID": parseInt(App.Prop.get("GroupID"), 10)
            });
        }

    });

    var group_users_view = new MyListView({
        tagname: "div",
        model: new MyListView.Model(),
        collection: new MyListView.Collection()
    });

My web method GetUsers takes 1 parameter, an integer named groupID. According to this page: http://backbonejs.org/#Collection-constructor, the initialize method inside MyListView.Collection is called when the Collection is created, which happens when MyListView is instantiated.

The error occurs inside the file jquery-1.12.3.js on the following line:

xhr.send( ( options.hasContent && options.data ) || null );

Here, options.data is undefined. However, the url property of options is correct. So why is jquery ajax not recognizing the data that I'm passing in?


Solution

  • By default, there is no relationship between this.options and the options object that is passed to the Ajax calls made to your server.

    If you read the source code of fetch, or sync you'll see they do not refer to this.options to build their options objects.

    If you need to set your data both for reading and writing you could override sync. And if you want all of this.options to be part of what is passed to jQuery.ajax, then you could have something like:

    sync: function sync(method, collection, options) {
      // It is okay for options to be undefined in the _.extend call.
      options = _.extend({}, options, this.options);
      return MyListView.Collection.__super__.sync.call(this, method, collection, options);
    },