I am creating a JSON object dynamically and when I send it via an ajax POST I get Disallowed Key Characters as the response. I know that my object is ok because I can create the SAME EXACT object manually and it sends fine. I tried escape() on all of my strings before adding them to the obj but that did not work either.
Am I missing something?
This is my post
$.ajax({
type: 'POST',
url: 'http://localhost/test',
data: obj,
dataType : 'JSON',
success: function(){
console.log('nice');
}
});
I am using the same obj as in this post
Add to JSON without knowing its structure
Your page encoding is probably not matching, it means the response can come with some invalid characters, for example:
ÿ¬{"Result":"A"}
You need to ensure that the encoding you are posting matches the encoding on the other side.
I just realized that my Keys have spaces in them
Yeah... the site you are connecting to is probably running CodeIgniter.
CI has some dumb broken input “cleaning” functionality that will deliberately refuse all form parameters with spaces in (or anything other than the alphanumerics and .-/:).
It turns out that this error was caused by CI's input library. On line 215 you will find _clean_input_keys function which uses preg_match() to disallow certain characters in your keys. So when you send JSON around and php recieves it as an array it can throw an error.
To fix this you can either extend the library or edit the CI core.
Related
I am creating a kafka broker in a cluster by sending a request to the url. According to the api it says that I can add additional options to my broker in the form /api/broker/<cli command>?broker={broker-expr}&<setting>=<value>, however the setting that I need to set has json as its value. How would I do this?
I've tried quite a few different ways of writing it at none of them work. The json value is meant to be
{
"period":"10s"
}
I've tried
/api/broker/remove?broker=0&stickiness={"period":"10s"}
/api/broker/remove?broker=8&stickiness={period:10s}
/api/broker/remove?broker=8&stickiness="{period:10s}"
Update:
I've tried encoding the url but it still doesn't work. Everything is decoded except for the :.
The string I enter for the json: %7B%22period%22%3A%22600s%22%7D
This is what it ends up as after I send it.
How do I encode a : ?
Only the first option you suggested is correct JSON. However, the JSON will need to be encoded.
Encoding just the JSON part results in %7B%22period%22%3A%2210s%22%7D
Check out the following site for more on URL encoding
http://www.w3schools.com/tags/ref_urlencode.asp
I have the current test I want to run:
var request = require('supertest');
it('should be malformed json', function(done) {
request(config.base)
.post('/authenticate')
.send('{"project":{"description":\'test"}}')
.set('Authorization', 'Bearer ' + config.token)
.expect('Content-Type', /json/)
.expect(status.BAD_REQUEST);
});
However, supertest seems to validate it, and it just sends '{}' in the body. Any idea how I can get around this?
You are passing a string to the send method, so it will be sent to the server as is (you could write anything there!).
Once the server receives the string, it parses the JSON and it finds the error. What happens next depend on how the server application is configured (or the framework you're using). It is possible that in this case the server just ignores any malformed JSON input, and thus it's like you called /authenticate without any input.
TL;DR: send() just sends any string you pass it. If you want to raise an error, you need to modify the server, and not the test suite.
EDIT
I did some more digging. First of all, as I said before, send() indeed leaves strings as is. You can see it from the code: https://github.com/visionmedia/superagent/blob/master/lib/client.js#L778
Thus said, you did not tell the server that the request body was in JSON format, so what you're saying is interpreted as "text/plain" and not parsed. To pass a manual JSON string to send() you also need to specify the content-type of the request:
request(config.base)
.post('/authenticate')
.type('json')
.send('{"project":{"description":\'test"}}')
//...
I'm trying to call a homemade vb.net web service using jQuery+Ajax and I'm struggling with the specifics.
Here's a small function exposed as a web method:
<WebMethod()> <ScriptMethod(ResponseFormat:=ResponseFormat.Xml, UseHttpGet:=True)> _
Public Function GetAllVotes() As XmlDocument
Dim theVotes = getVotes()
Dim strResult As String = theVotes.XMLSerialize
Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml(strResult)
Return doc
End Function
After looking the web I've added the ScriptMethod attributes since i was returning XML but feel free to tell me i don't need them if that's the case.
Then, on the client side, this is the code :
function getVotes() {
$.support.cors = true;
$.ajax({
type: "GET",
contentType: "application/json",
url: "http://nhrd635:8008/votingmanager.asmx/GetAllVotes",
data: {},
dataType: "xml text jsonp",
success: function(msg) {
// Hide the fake progress indicator graphic.
// Insert the returned HTML into the <div>.
$('#myPlaceHolder').html(msg);
},
error: function(msg) {
$('#myPlaceHolder').html(msg);
// alert(msg);
}
});
}
I've tried many .. many variations of this code, using post or get, changing the content-type, with or without charset=utf-8. with and without double quotes on data: {}.
i use firebug to trace the output my request. only when i set dataType to jsonp do i ever get a result, but in all instances, the code ends up on the "error" function, even when status give 200 OK. but i know that setting it to jsonp is wrong since that gets my xml treated as actual javascript...
I've read very useful blog entries from a guy on encosia.
(sample: http://encosia.com/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/)
but even following his examples i am unable to get a proper return.
am i doing something wrong that's very obvious? is it the fact that i am returning an xml string rather than a json serialized string?
With more perusing of Stack Overflow and the help of Dave Ward from Encosia, I've managed to solve my problem. I've thought I should post my final solution here, in case that helps someone in the future.
First of all, Web Services were a bad way of doing it, I went with the HttpHandler solution, as suggested by Dave Ward in reply to my original question.
Returning XML was also a poor choice, that I wasn't really aware of. I added a reference to JSon.net to my project and used it to transform my object into a Json string.
I really wanted to stick to ".net only" to transform into a json string, as suggested in Dave's blog post, but somehow I struggled to learn how to instruct .net to automatically transform into Json as in Dave's example, so i took an easy way out with Json.net to "get it working"
Then, in my HttpHandler, I had the response string follow the instructions on this post from StackOverflow:
https://stackoverflow.com/a/3703221/1060133
in my case, it was :
context.Response.Write(String.Format("{0}({1});", context.Request("callback"), jsonVotes))
The jquery call also used the instructions in the above post.
Interesting note, even in a parameter-less call, you have to send empty data like so:
$.getJSON('http://url/httpHandler.ashx?callback=?', {},
function(data) {
alert(data);
}
);
Best of luck...
I think most of your trouble here probably stems from the cross-origin request (even making a request across different ports on the same machine counts). That's why you were able to get a glimmer of it working when you switched to JSONP. Unfortunately, ASMX "ScriptServices" don't support JSONP, so the data your WebMethod returned wouldn't be a valid parameter to the JSONP callback function that jQuery injects.
The best solution, if at all possible, is to get the service running on the same domain as the page that's calling it. There are various solutions to the cross-origin problem, but none of them are as widely compatible/reliable as a simple XHR request to the same domain that the page making the request resides on.
If you can't do that, consider enabling CORS support for the site serving up votingmanager.asmx. That doesn't work in most versions of IE, but will allow cross-origin requests in other browsers. More info on how to do that here: http://encosia.com/using-cors-to-access-asp-net-services-across-domains/
Tangentially, I'd avoid the extra XML serialization layer if possible. If getVotes() returns something like a List, use that as your return type and let ASP.NET automatically serialize the collection as JSON and then jQuery will automatically convert that to a JavaScript array in your success handler. More info about that here: http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/
I'm trying to submit a form with a file field in it via jQuery.Form plugin, here's the code:
$('form').ajaxSubmit({
url: "/path",
dataType: "json",
contentType: "multipart/form-data"
...
The server then returns json as a response. Works great in all browsers except IE, which tries to download the response as a file. If I remove the file field from the form, it also works just fine.
I've seen various solutions here and in Google and basically tried almost everything described, including setting enctype for the form via jQuery, but it didn't work.
Any suggestions would be very welcomed.
You can simply return JSON from the controller as "text/html" and then parse it on the client side using JQuery.parseJSON().
Controller:
return this.Json(
new
{
prop1 = 5,
prop2 = 10
},
"text/html");
Client side:
jsonResponse = $.parseJSON(response);
if(jsonResponse.prop1==5) {
...
}
This solution has been working for me.
I have not found a direct solution to this, but I eventually implemented the following workaround: I used dataType: "text" in my ajax settings and then returned plaintext from controller, separating values with ; and parsing them on the client side. That way IE and Forefox stopped trying to download a response.
I did not find any other way to prevent said behavior other then to return plaintext. I tried returning JSON as plaintext and then parsing it with $.parseJSON, but it didn't work due to some js errors.
Just send response with 'Content-Type', 'text/html' header.
Just set Content-Type: text/html
This happens because IE8 doesn't recognize application/... mimetype.
This works for me.
Hope it helps.
Same situation than you folks : the problem only occurs with enctype="multipart/form-data" form used with $(form).ajaxSubmit(...) function.
My team and I had to replace (in this function) dataType: 'json' option with dataType: 'text' and add responseText = $.parseJSON(responseText); to force server response parsing.
Of course we also had to step in server side to return a response with "text/plain" header instead of "application/json"
We're not proud of it :( IE is definitely killing everything...
I didn't try the advice given by zmonteca (already spent too much time on it) but it seems worthy : let us know if it was OK for you.
Hope it helps!
if you work with Zend you can do
$this->getResponse()->setHeader('Content-Type', 'text/html');
in your controller action. and on client-side, in case of jQuery, you can do
data = $.parseJSON(data);
This site has some info about wrapping the response in a
http://forum.jquery.com/topic/jquery-form-malsup-ie7-file-download-security-warning-on-ajax-file-upload
I seemed to be able to fix my problem by making my server return the JSON as a string.
Then I used JSON.parse() inside the complete event.
I came up with the following workaround (in Zend Framework):
if (!$this->_request->isXmlHttpRequest()) {
die('<textarea>'.Zend_Json::encode($data).'</textarea>');
}
$this->view->assign($data);
Removing ContentType from serverside works for me.
I'm building an application that communicates with a django backend using json-rpc. So far all has been working well. However I've found an anomaly in sending " ". As far as I know the request works fine, however django interprets the response badly. I've reproduced a simplified request and response below:
Request:
{"jsonrpc":"2.0","id":"1","method":"test","params":
{"id":"80","name":"tests","introduction":"hello there"}}
Django receives:
<QueryDict:u'{"jsonrpc":"2.0","id":"1","method":"test","params":
{"id":"80","name":"tests","introduction":"hello ': [u''], u'nbsp': [u''], u'there"}}': [u'']}>
Expected response:
<QueryDict: {u'{"jsonrpc":"2.0","id":"1","method":"test","params":
{"id":"80","name":"tests","introduction":"hello there"}}': [u'']}>
It seems like django interprets the & and the ; as special characters and so creates an unexpected dictionary in its request.POST variable.
What do I need to do to make sure that the json string doesn't get malformed? I have tried encoding it using the php htmlspecialchars() method, but since that doesn't remove the '&' the problem persists.
Any help will be much appreciated.
Django is handling the (POST?) request by decoding the body (your json string) as if it were a query string, and not a json.
Within a query string, & and ; denote the end of a key:value pair. Splitting up your request body on those two characters yields the key:value pairs you see in the Django QueryDict.
You need to get hold of the POST request body and explicitly decode it to a dict yourself using either the standard lib json, or simplejson module.
I have little experience with Django specifically, but I imagine that somewhere in your view handler you would do something akin to:
try:
data = json.loads(requesst.raw_post_data)
## work with the data...
except ValueError:
## do something...
No doubt Django provides a way to move this json handling out of your views, and to somewhere more suitable.