Hi, I have come across a problem / nuance in how angular resource executes POST queries and shall try to explain here (as an example);
Say we have a backend that hosts an endpoint "/users/find"
This endpoint accepts POST requests however will return data like a GET so you can send a json object { "firstName": "John" }
to the endpoint /users/find?skip=5&limit=20
when used like this the endpoint returns data where the database matches the request filter e.g. [{ id: 1, firstName: "John", contactNumber: "123456789" }, {.....} ]
.
However, when calling this using Angular you create a resource like:
.factory('User', function ($resource) {
return $resource('/users/:id', {}, {
find: { method: 'POST', url: '/users/find', params: { skip: 0, limit: 20 }, isArray: true },
})
})
and the service is then called in the controller like:
User.find({ "name": "John", "skip": "5" })
The result is that Angular then makes a POST call to:
/users/find?skip=5&limit=20
with a payload of:
{ "name": "John", "skip": "5" }
This results in no users being found as there is no field in the db called "skip" so the search requirement of name and skip is not valid in the payload
What is the best solution? Well I was going to write a replacement for the angular resource but felt it would mean copying all the angular code an making some tweaks.
I would suggest angular adds an extra parameter to the resource function like payload rather than using params as both the payload and query string, but this would be quite a fundamental change?
I hope this issue entry makes sense and please feel free to ask questions.
Many of us agree that this is a good change. In the meantime, please modify your backend to ignore the skip
field.
Actually, you should be able to use the overloaded method(params, payload)
signature.
User.find({ "skip": 5 }, { "name": "John" })
That worked great, cant believe I had missed that you already cater for what I said, well done guys, and thanks again :)
How can we post all page content including html and svg on post ??
I think this does not relate to the original issue here, however to be brief, I assume you are after a multipart form submission via angular?
To do this I use the request transform personally, for example something like:
multipartEndpoint = $resource('/path/to/api/resource', null, {
upload: {
method: 'POST',
headers: { 'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
formData.append("data", angular.toJson(data.model));
angular.forEach(data.files, function (fileData) {
formData.append(fileData.name, fileData.binary);
});
return formData;
}
}
});
Then if you can't tell form the code then angular is reading the file contents to set the "binary" field and the "model" is just a standard JS object. The beauty of doing it this way is you can still test everything rather than making your own XHR object etc etc...
The content-type is set as undefined to allow the browser to decide on the multipart settings which should pick up SVG fine (this works for PNG, JPG, Octet-Streams etc so can't see why SVG would not).
If this does not answer your question then perhaps make a new issue rather than resurrecting this old one!
Most helpful comment
Actually, you should be able to use the overloaded
method(params, payload)
signature.