Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone model.save() not appending ID to end of URL

I have an issue with a backbone PUT request returning 405 (Method not allowed). This is happening because the model.save() in the code is not sending to the model url with the ID of the model on the end.

This is the PUT.

Remote Address:::1:670
Request URL:http://localhost:670/api/contacts
Request Method:PUT
Status Code:405 Method Not Allowed
Request Headersview source
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Authorization:Bearer YLPwKSpBsBrFUemRHdjz....
Connection:keep-alive
Content-Length:417
Content-Type:application/json
Host:localhost:670
Origin:http://localhost:660
Referer:http://localhost:660/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)     Chrome/34.0.1847.116 Safari/537.36
Request Payloadview source
{id:1, ContactOrganisation:Cow on a Mission, ContactPerson:Ben Drury, Phone:07980567574,…}
Address: "----"
ContactOrganisation: "----"
ContactPerson: "Ben"
CreatedBy: "----"
CreatedOn: "2014-03-03T16:40:50.037"
Description: "----"
Email: "---"
Organistion: "----"
Phone: "----"
Website: "http://www.cogiva.com"
id: 1
Response Headersview source
Access-Control-Allow-Headers:Authorization, Content-Type
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Allow:GET,POST,OPTIONS
Cache-Control:no-cache
Content-Length:72
Content-Type:application/json; charset=utf-8
Date:Thu, 17 Apr 2014 13:56:38 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
ConsoleSearchEmulationRendering

If I do the put through a REST console and add the id to the URL it works. But direct from this code:

      this.model.set($(e.currentTarget).data("modelfield"), $(e.currentTarget).val());
      console.log("model",this.model);
      this.model.save({
          success: function(model, response){
            console.log("Yup!");
            $(self.el).find('.update_loader').removeClass("running");
            $(self.el).find('.update_loader').addClass("done");
          },
          error: function(){
            console.log("No!");
            $(self.el).find('.update_loader').removeClass("running");
            $(self.el).find('.update_loader').addClass("error");                
          }
      });

The model on the console just before the post, definitely had an ID. Why would it not be forming the URL correctly?

Model Def:

define([
'jquery',
'underscore',
'backbone',

], function ($, _, Backbone){

    var ContactModel = Backbone.Model.extend({
      url: "http://localhost:670/api/contacts"        
    });

    return ContactModel;

});
like image 894
Ben Drury Avatar asked Apr 17 '14 14:04

Ben Drury


3 Answers

Setting Model.url just gives the model a constant URL. If you want the model ID appended, then you need to specify Model.urlRoot instead. This will generate URLs of the form "/api/contacts/id":

var ContactModel = Backbone.Model.extend({
  urlRoot: "http://localhost:670/api/contacts"        
});

Alternatively, if the model is stored in a collection, then you could set Collection.url to the same. See the notes for Model.url:

Delegates to Collection#url to generate the URL, so make sure that you have it defined, or a urlRoot property, if all models of this class share a common root URL. A model with an id of 101, stored in a Backbone.Collection with a url of "/documents/7/notes", would have this URL: "/documents/7/notes/101"

like image 191
McGarnagle Avatar answered Nov 02 '22 13:11

McGarnagle


You overwrite the url property. That's why it's fixed - backbone calls this property/function to get the url. And the default url function implementation uses urlRoot. Change code to this should work:

var ContactModel = Backbone.Model.extend({
  urlRoot: "http://localhost:670/api/contacts"        
});

Check this: model.url

If your url format is special (not urlRoot/id) you need to overwrite url with a function to provide custom implementation.

like image 3
Gildor Avatar answered Nov 02 '22 13:11

Gildor


You mask the default behavior of Model.url by setting an explicit url attribute on your ContactModel definition. Use Model.urlRoot instead:

var ContactModel = Backbone.Model.extend({
  urlRoot: "http://localhost:670/api/contacts"        
});
like image 2
nikoshr Avatar answered Nov 02 '22 13:11

nikoshr