parse JSON response in IE9 - json

In my MVC4 web app I'm using FineUploader to upload files.
When a file is uploaded I send a json response from my controller like so:
return this.Json(packageUploadResult, "text/plain", System.Text.Encoding.UTF8);
I had to modify "application/json" to "text/plain" because I was getting "Save As" "Open" options in IE (info here). ONLY IN IE. It works fine in all other browsers.
View:
...
}).on('complete', function (event, id, filename, json) {
if (json.success) {
if (json.IsSignature) {
alert("IN");
}
...
How can I parse Json response to make it work in IE:
sample response:
{"PackageErrorType":0,"PackageId":"AGI-MM-CFG-NUB-2.0.1.2.2","SignatureMatch":false,"IsSignature":false,"success":true}

You could parse the text/plain returned by the server using the $.parseJSON method:
var json = $.parseJSON(textReturnedByServer);
if (json.success) {
if (json.IsSignature) {
alert("IN");
}
}
Of course you should do this only for the legacy browsers that do not support HTML5 File API such as Internet Explorer.

Related

Angular: Observable with subscribe returns error 200 OK as the response is not JSON

I am developing a front-end web application using Angular 11. This application uses several services which return data in JSON format.
I use the async / await javascript constructs and the Observables to get the answers from these services. This is an example my call:
let myResponse = await this.myService(this.myData);
myResponse.subscribe(
res => {
console.log("Res: ",res)
}, (error) => {
console.log("Error: ",error)
}
);
where this.myService contains the code doing the HTTP call using Angular httpClient.
Unfortunately a specific service (only one!) doesn't return data in JSON format but it returns a byte array (string that identifies a pdf -format application/pdf-).
Unfortunately this invocation causes a very strange error with code 200 OK:
How can I do to prevent res from being interpreted as JSON and therefore this error being reported? How can I read resreporting that it will not be in json format?
This service has no errors (with Postman it works perfectly). The problem is Javascript and Observable which are interpreted as JSON. How can I read the content of res in this case?
If a HTTP API call is not returning a JSON, just provide the proper value in the responseType option:
this.httpClient.get('<URL>', {
responseType: 'arraybuffer'
});
Ref: https://angular.io/api/common/http/HttpClient#description

How to get indented JSON output in asp.net MVC 5 to view in browser?

This is only for debugging purpose. Only returning JSON, outputs unreadable JSON string on webpage. Is there any quick solution to view formatted json on webpage?
Looking for a C# function that will take json object and return formatted output as string from my action method.
Just change JSON global settings in your Global.asax file.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented
};
It should produce indented JSON for all your Web API endpoints.
Then you can inspect resulting JSON directly in browser or using some HTTP traffic capturing tool like Fiddler.
Use the JavaScript JSON.Stringify() function. Example:
$.ajax({
method: "POST",
url: "/yourController/yourAction",
data: { name: "John", location: "Boston" }
}).done(function( data ) {
alert(JSON.Stringify(data));
});

Issue decoding JSON after Ext.Ajax.Request

I'm facing issues with ExtJS 4.1.3.
In my ExtJS controller, I call an ajax request like this :
Ext.Ajax.request(
{
url: '/my/url/method.do'
,timeout: 1800000
,jsonData: param
,success:function(response)
{
var jsonData = Ext.JSON.decode(response.responseText);
alert(jsonData);
// some code
}
,failure:function(response)
{
// some code
}
,scope:this
}
);
This is the method called in spring :
#RequestMapping(value = "/my/url/method.do")
public #ResponseBody String method(Locale userLocale, #RequestBody Param[] param) {
return "string" + "<br/>" + "string";
}
It works well on Google Chrome and IE but not on Firefox. Indeed, I get the following error :
Ext.Error: You're trying to decode an invalid JSON String: string<br/>string
And I don't know why it doesn't work because if I execute the following code in the Firefox console, it works :
Ext.JSON.decode("string<br/>string")
So if anyone could help me, I would be grateful !
Thanks for your answers.
This website http://jsonlint.com/ indicates "string<br/>string" as a valid JSON string. But it is a "false" JSON validation cause it is not proper JSON format.
I solved my problem adding produce="application/json" in the #EequestMapping annotation of the controller. So now Ext.JSON.decode() works even with Firefox.
I could also send back an object serializable with the ajax request and then decode the response to get the data (with my string in it) because Spring automatically serialize object to JSON.

Download .csv with Play! framework

EDIT
From what I have learned (from comments by nico_ekito) it is not possible to use ajax call to download a file. The solution is to create a hidden <iframe> that will download the file, described here.
Problem:
The browser doesn't show download dialog. Any browser - ff, opera, chrome, safari, ie.
I read the docs about serving files, found this question and, based on this, wrote:
Controller.response().setContentType("text/csv");
Controller.response().setHeader("Content-Disposition", "attachment;filename=public/export/filename.csv");
Controller.response().setHeader("Cache-control", "private");
return ok(CSV.export(data, filename));
Where CSV is a class:
public class CSV{
public static File export(Map<String, String> data, String filename){
String csv = data.get("data[saveMe]");
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("public/export/" + filename), "UTF-8"));
bw.write(csv);
bw.newLine();
bw.flush();
bw.close();
}catch(UnsupportedEncodingException e){}
catch(FileNotFoundException e){}
catch(IOException e){}
File downloadMe = new File("public/export/" + filename);
return downloadMe;
}
}
On client side, I use dojo to send POST request (I also tried with GET, result is the same):
xhr.post({
url: '/exportData/',
content: {
saveMe: str
}
}).then(function(response){
//do sth
});
Response headers look like that:
Cache-Control private
Content-Disposition attachment;filename=public/export/filename.csv
Content-Type text/csv
Transfer-Encoding chunked
POST tab in firebug shows proper data in proper csv format. To format data with csv style I use dojox/grid/enhanced/plugins/exporter/CSVWriter
I think it is not possible to download a file from an Ajax request, see this question: Allow User to Download File using Ajax
You should either use an iframe as suggested in the question, or use a standard HTML form containing your data, and do a post on this form.

IE9 JSON Data "do you want to open or save this file"

Started testing my jQuery applications with IE9. Looks like I may be in for some trouble here.
I noticed that when I return JSON data back to the Javascript methods I always get this Prompt that says: "Do you want to open or save this file?" and provides me with 3 buttons: Open, Save and Cancel. Of course, my javascript is taking actions based on the values set in the JSON object but since IE9 doesn't pass it over to the script, I cannot execute the follow up action from there on.
Anyone else facing this issue? Here is a snapshot.
If anyone is using ASP.net MVC and trying to fix this issue - I used the following built in methods in the MVC framework. Simply update the content Type and encoding on the JsonResult.
public ActionResult Index(int id)
{
// Fetch some data
var someData = GetSomeData();
// Return and update content type and encoding
return Json(someData, "text/html", System.Text.Encoding.UTF8,
JsonRequestBehavior.AllowGet);
}
This fixed the issue for me!
(Answer originally posted for this question.)
If using MVC, one way of handling this is to implement a base controller in which you override (hide) the Json(object) method as follows:
public class ExtendedController : Controller
{
protected new JsonResult Json(object data)
{
if (!Request.AcceptTypes.Contains("application/json"))
return base.Json(data, "text/plain");
else
return base.Json(data);
}
}
Now, your controllers can all inherit ExtendedController and simply call return Json(model); ...
without modifying the response content type for those browsers which play nicely (not <=IE9 !)
without having to remember to use Json(data, "text/plain") in your various Ajax action methods
This works with json requests which would otherwise display the "Open or Save" message in IE8 & IE9 such as those made by jQuery File Upload
I also faced this problem yesterday with WebAPI which returned a list of URLs (of asynchronously uploaded files).
Just set content type to "text/html" instead of default "application/json; charset=UTF-8" of WebAPI services. I got response as a JSON string and then used $.parseJSON to convert it to JSON object.
public async Task<HttpResponseMessage> Upload()
{
// ...
var response = Request.CreateResponse(HttpStatusCode.OK, files);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return response;
}
// result is an iframe's body content that received response.
$.each($.parseJSON(result.html()), function (i, item)
{
console.log(item.Url);
});
In my case when contentType in response header is "application/json; charset=UTF-8", the IE 9 shows that Prompt. But changed to "text/html" then the prompt does not show, although all otter browsers are fine with the "application/json; charset=UTF-8".
Actually, you were right #EricLaw. After setting the content type in the Json result, it worked.
I had to add the following lines:
result.ContentEncoding = System.Text.Encoding.UTF8;
result.ContentType = "application/json; charset=UTF-8