What do browsers want for the Content-Type header on json ajax responses? - ajax

I am returning some json which needs to be handled by javascript as the response to an XMLHTTPRequest.
If I set the response's content type to "text/plain", all browsers but Chrome will accept it and pass it to my JS with no problem. However, Chrome will wrap the response in
<pre style="word-wrap: break-word; white-space: pre-wrap;">
before passing it to my javascript.
If I set the response's content type to the "proper" "application/json" all browsers but Firefox will accept it and pass it to my JS with no problem. Firefox, however will ask to save or open the response as a file.
What's the correct, cross-browser Content-Type?

You may solve the issue by parsing the response into the JSON object by using jQuery funcion parseJSON - http://api.jquery.com/jQuery.parseJSON/
The parameter you pass into the function is the JSON object string, which you extract from the response data:
function AjaxResponse (data) { // AJAX post callback
var jsonResult = $.parseJSON(data.substring(data.indexOf("{"), data.lastIndexOf("}") + 1));
}
Tested (besides Chrome which problem this solves) in FF and IE8 for the following simple JSON result, for other browsers and more complex responses no guarantees...
NOTE: the content type in this case is text/plain or text/html I think - I've used the following ASP.Net MVC function to return the result
ContentResult System.Web.Mvc.Controller.Content(string content);
Where I returned the JSON object like
System.Web.Script.Serialization.JavaScriptSerializer jsonSerializer
= new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonResponse = jsonSerializer.Serialize(
new { IArticleMediaId = 0
, ImageUrl = Url.Content(fullImgPath)
});
return Content(jsonResponse);

In ajaxFileUpload.js in uploadCallback() replace
io.contentWindow.document.body.innerHTML.innerHTML
with
$(io.contentWindow.document.body.innerHTML).html()

Related

How to avoid multipart/form-data with XMLHTTPRequest and FormData

I'm trying to setup an html form, the form action is an aws lambda function.
When I submit the form via plain html, all is well. However, when I'm sending the form via XMLHTTPRequest + FormData the lambda function breaks.
Looking at the lambda logs it seems that when using the plain html form send, the form is encoded in the request body as straight forward query string ('name=Johnny&email=john%40bon.com' etc) which my lambda function can parse.
However, when using XMLHTTPRequest+FormData to send the form, the form is encoded in using a different format which I believe (not sure) is called multipart/form-data (has these WebKitFormBoundaryXXX additions).
Is there a way to make XMLHTTPRequest+FormData send the form in the same format as is used when sending the form via plain html. Alternatively, how to do parse this multipart/form-data format in aws lambda python.
const form = document.querySelector('#my-form-id')
form.addEventListener('submit', event => {
// disable default action
event.preventDefault()
// configure a request
const xhr = new XMLHttpRequest()
xhr.open('POST', 'www.myurl.com/submit')
// prepare form data
let data = new FormData(form)
// set headers
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// send request
xhr.send(data)
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText)
}
})```
Is there a way to make XMLHTTPRequest+FormData send the form in the same format as is used when sending the form via plain html.
Well. It does… for a value of plain HTML with enctype='multipart/form-data'.
If you want to send application/x-www-form-urlencoded data then FormData is the wrong tool for the job.
Use URLSearchParams instead.
You can initialise it with a FormData object.
const data = new URLSearchParams(new FormData(document.querySelector('form')));
console.log(`${data}`);
<form>
<input name=foo value=bar>
<input name=x value=y>
</form>
Note that XMLHttpRequest can infer the Content-Type header when you pass a URLSearchParams or FormData object to send() so don't set it manually. That is just a waste of time and an opportunity to introduce errors.
Quentin's solution works. Here's the corrected code:
form.addEventListener('submit', event => {
// disable default action
event.preventDefault()
// configure a request
const xhr = new XMLHttpRequest()
xhr.open('POST', 'www.myurl.com/submit')
// send request
xhr.send(new URLSearchParams(new FormData(form)))
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText)
}
})```

MVC unobtrusive AJAX, returning Json data, and IE

So there are lots of questions out there about this whole "IE opens a download file dialog for Json data returned via Ajax" (like this one or this one), but I have not found any answers for those who use Unobtrusive Ajax.
We do a simple Ajax.BeginForm like this:
Ajax.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl },
new AjaxOptions { UpdateTargetId = "ContentContainer", OnSuccess = "JsonCheckRedirect" },
new { id = "form1" }
)
This posts the form with Content Type of "application/x-www-form-urlencoded; charset=UTF-8". The Controller processes the form, and if there is an error, it returns a PartialView with Content Type "text/html", and that HTML gets put into the ContentContainer (because of the "UpdateTargetId" property in the AjaxOptions).
If there is no error, and the user logged in successfully, it returns Json with the URL they should be redirected to. So in the Controller, it's just simply this:
return Json(new { Url = returnUrl });
Except that we just had a user notify us that in IE8, this is causing the download dialog to pop up. After reading all these other questions with the same issue, I understand why this is happening, but the fix for those situations is to use this Json return instead:
return Json(new { Url = returnUrl }, "text/html");
The problem is that when I return like this, I guess Unobtrusive Ajax sees that the response from the server is HTML, and it replaces the content in the UpdateTargetId container. It does not do this when the server responds with "application/json".
Is there any way around this?
(do I need to explain anything further?)
If you return the url like that, you are going to need to override the Success handler and check the result to see if it has the Url property and then putting the result into window.location.
Personally, rather than returning a new Json result, I would send back a 302 which should make the ajax handler redirect you.
This happens in the bowels of jQuery if memory serves, so you don't need to change anything.
So rather than returning that json result on a successful login, try using a redirectToRoute result instead and send them to the page you want them to go to.

Django character wrong encoding for Ajax request

I have a form which is generated from a database. In the database I have strings such as 'Española' which will become options in a drop down menu.
A the moment my html looks like:
<option value="Española">Española</option>
I am using these values for a dynamic part of the form from which I need to send AJAX requests.
I can see that, when using IE, the header is like so:
GET /collections/find_island?island_group=Espa�ola HTTP/1.1" 500 63206
when it should be:
GET /collections/find_island/?island_group=Espa%C3%B1ola HTTP/1.1" 200 164
As generated by other browsers.
Is there some way I can get this output in my template:
<option value="Espa%C3%B1ola">Española</option>
Any help much appreciated.
EDIT:
My form:
def form(forms.Form):
...
island_group = forms.ModelChoiceField(
required=False,
label=ugettext_lazy('Island Group'),
initial=None,
queryset=Localityonline.objects.values_list('islandgroup', flat=True).distinct('islandgroup').order_by('islandgroup'),
empty_label=ugettext_lazy("Not Specified"),
widget=forms.Select(attrs={"class":'searchfield', "onChange":'getIslandName()'})
)
the javascript:
function getIslandName(lang) {
var islandGroup = document.getElementById("id_island_group").value;
if (islandGroup == '') {
// if Not Specified re-selected then set data to null and bypass updatePage()
var data = null;
update_select($('select[name=island_name]'), data);
}
else {
var url = "../collections/find_island?island_group=" + islandGroup;
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
}
You can call encodeURI in javascipt to give the encoded value that you are looking for. Perhaps mozilla and chrome do it automatically and IE doesn't???
encodeURI('Española')
// "Espa%C3%B1ola"
var url = "../collections/find_island?island_group=" + encodeURI(islandGroup);
or encode the whole url I don't know which one makes more sense...
Encode URL in JavaScript?
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURI

Information Bar appears in IE8 while downloading

I have an application in which there are options to Export the document in Word/PDF format. We do a form submit to post the HTML and send it to the server for conversion. In the back-end the servlet writes it back to client after setting a contentType. The Information Bar appears during the first download only.
I cannot recommend users to reduce their Browser Security levels. Hence i need a solution to by-pass this alert. I saw that Google Docs has handled this. Does anyone have an idea about what needs to be done ?
I'm using the following JQuery code:
$.download = function(url, data, method){
//url and data options required
if( url && data ){
//data can be string of parameters or array/object
data = typeof data == 'string' ? data : $.param(data);
//split params into form inputs
var inputs = '';
$.each(data.split('&'), function(){
var pair = this.split('=');
inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
});
//send request
$('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
.appendTo('body').submit().remove();
};
};
And each time download should be initiated, I'm firing
$.download(options);
Server response is with proper content-type headers (e.g. Word).
Maybe you have forgotten to remove submitted form from the DOM?

jQuery 1.5.2 displays [object XMLDocument] for empty responses

I have a Url from which I can get a string
If the response string contains something, everything goes well, but (god forbid!) if the result would be an empty string like "" jQuery 1.5.2 will display it as [object XMLDocument]
follow the codes plz :
$.post('/Applicant/RequestedJob/IsThereActivePeriod',{},
function(data){
if(data == '' )
{
//do something here!
}
else
{
console.log(data.toString());
// [object XMLDocument] will be printed in console.
}
});
Perhaps I should mention that it used to work perfectly on jQuery 1.4.4
any idea?
Regards :)
You should set the expected dataType of the response in your ajax call, like this:
$.post('/Applicant/RequestedJob/IsThereActivePeriod',{},
function(data){
if(data == '' )
openDialog('/Applicant/RequestedJob/AddRequestedJobWindow','pnlRequestedJob','Request Window');
else
{
msgbox.show(data.toString(),'Error', msgBoxButtons.okOnly);
console.log(data.toString());
}
},
'html'
);
Without this, jQuery tries to infer the response type, according to this:
Default: Intelligent Guess (xml, json,
script, or html).
With no returned content, it's apparently guessing XML. By passing it 'html' as the dataType, you force jQuery to interpret the response as HTML, and store the result in plain text.
As per some of the comments, an appropriate content-type header should allow jQuery to infer that your empty string is HTML, achieving the same result without setting the expected dataType explicitly in the ajax call.
The reason you get [object XMLDocument] is because data is an XML document object, and its toString() is being called.

Resources