Closed Nithanaroy closed 6 years ago
Something changed between 3.8 and 3.9:
https://jsbin.com/zicesev/edit?html,js,output
Thanks for reporting.
Ok, so CanJS behaves the right way. For example, this JSBin doesn't load jQuery and works right:
https://justinbmeyer.jsbin.com/zicesev/2/edit?html,js,output
This one does load jQuery:
https://justinbmeyer.jsbin.com/himison/2/edit?html,js,output
and works wrong.
The fix would be to make sure can.ajax
is being used like:
var Type = can.DefineMap.extend({
id: "string",
name: "string"
});
Type.connection = can.connect.baseMap({
Map: Type,
url: "/place"
});
Type.connection.ajax = can.ajax;
new Type({name: "something"}).save()
How are you checking the request body for .save()
in the above JS Bin?
How are you checking the request body for .save() in the above JS Bin?
using the network tab:
What's also very odd is that if you do:
Type.connection = can.connect.baseMap({
Map: Type,
url: {resource: "/place", contentType: "application/json"}
});
we call jQuery with:
And it still sends the data out as form data. I wonder if this is something that changed with jQuery?
My guess is that jQuery doesn't see contentType: "application/json" and automatically
JSON.stringify` its data. I'm not sure what to do about this.
Is there a way temporarily solve this while the complete solution is figured out? Like versioning down the can-connect library etc?
@Nithanaroy did you try setting Type.connection.ajax
to use can-ajax
like mentioned in https://github.com/canjs/can-connect/issues/348#issuecomment-327936491?
I showed the fix above
For setting the connection,
Type.connection.ajax = can.ajax;
should I import entire can
like import can
or can I just import can.ajax
property?
It sounds like you’re already using the individual modules (like can-connect
), so I would npm install --save can-ajax
and then:
import ajax from 'can-ajax';
// ...your model code
Type.connection.ajax = ajax;
...
"url": "/api/v1/entity",
"method": "POST",
"contentType": "application/json",
"data": JSON.stringify( entityObjDataToSave ),
This jQuery snippet correctly sends the request body as JSON
May be this can be added to can-ajax
wrapper of jQuery?
@justinbmeyer
My guess is that jQuery doesn't see
contentType: "application/json"
and automaticallyJSON.stringify
its data. I'm not sure what to do about this.
You can register a pre-filter to force jQuery to do the right thing for a JSON content type and compatible HTTP methods.
E.g.
$.ajaxPrefilter( function ( options, orig, xhr ) {
// If data should be processed internally and the content-type and
// http method indicate JSON, ensure that the data is delivered as
// a JSON-encoded string and not as form-encoded values.
if ( options.processData
&& /^application\/json((\+|;).+)?$/i.test( options.contentType )
&& /^(post|put|delete)$/i.test( options.type )
) {
options.data = JSON.stringify( orig.data );
options.processData = false;
}
});
How often can you reproduce it?
Description: We are using can-connect, ^1.3.6. Observed the recent change in model.save() behavior from sending JSON data (to server) to url-encoded format. We are using baseMap() with our models and unable to save due to request data format change. Any ideas on how to change this setting in baseMap?
Steps to reproduce:
Create a Model with can-connect 1.5.7 and call
modelInstance.save()
. Observe the request body format.Expected results: JSON request body
Actual results: form encoded request body
Environment: