parsing a reponse from a XMLHttpRequest - ajax

I'm struggling with how to parse a response from an XMLHttpRequest. The response is in json format:
http://flickr.com/services/rest/?method=flickr.photos.search&api_key=75564008a468bf8a284dc94bbd176dd8&tags=paris&format=json
to make sure it does indeed come in as such i tested it:
document.getElementById('info').innerHTML = this.responseText
which returns me a page with a long line of data written in json format. Could someone help me figure out the next steps in order to extract data from the response i.e. a list of all titles
i did some research and came across this:
response = this.responseText ;
var doc = new DOMParser().parseFromString(response, "text/xml");
what do i need to do next?
(Note: i wish to do this manually i.e. without the help of jQuery or similar tools.)
[EDIT]
based on the suggestions below and on the Flickr page on that matter, i have tried the following:
request.onreadystatechange = function()
{
...
if (this.responseXML != null)
{
jsonFlickrApi(this.responseText) ;
function jsonFlickrApi(rsp){
for (var i=0; i<rsp.photos.photo.length; i++){
var blog = rsp.photos.photo[i];
var div = document.createElement('div');
var txt = document.createTextNode(photo.owner);
div.appendChild(txt);
//document.body.appendChild(div);
document.getElementById('info').innerHTML.appendChild(div);
}
...
}
this doesn't return anything visible yet.
[EDIT2]
further troubleshooting reveals:
rsp = this.responseText ;
document.getElementById('info').innerHTML = rsp.stat ;
prints undefined

The URL you've given returns somethins like this :
jsonFlickrApi({"photos":{"page":1, "p ... , "stat":"ok"})
So, basically, it looks like Javascript code, which :
Calls the jsonFlickrApi function,
Passing it a big JSON object as a parameter.
First of all, here, you are working with JSON, so you should not use any DOM-related stuff : DOM functions' goal is to help manipulate XML.
Instead, you should :
Write a jsonFlickrApi function,
Make sure it's called when you receive the data from Flickr
About that, you shuld find a bit more informations, and an example, here : http://www.flickr.com/services/api/response.json.html
Else, adding the &nojsoncallback=1 parameter at the end of the URL of your request, you'll get pure-JSON as a result (and not a function-call).
That would allow you to use standard JSON-manipulation functions to work with that data, not having to implement any specific function.
Between those solutions, up to you to choose which one you prefer :-)

A different alternative is not to use JSON at all, and use XML instead. Leave out the format=json part of the URL and you get the data as XML. This XML can be parsed, for example with the DOMParser() method you tried, or with this.responseXML. However, the "logistics" of using XML, compared to JSON, are a bit more complicated, as you're browsing a DOM tree and not a JS object.
Update:
So here's one of the murky details of AJAX. Depending on the browser, you can't just make XML requests between domains. The following code will work (return something useful) on Safari, but not Firefox or Chrome. (There, it will return null or empty strings.) The JSON requests seem to work fine without on all browsers, however.
<script>
function createXHR(){
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject){
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
function getFlickr(){
xmlhttp=createXHR();
url="http://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=75564008a468bf8a284dc94bbd176dd8&tags=paris&";
xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function stateChanged(){
if (xmlhttp.readyState==4){
alert(xmlhttp.getAllResponseHeaders());
alert(xmlhttp.responseXML)
alert(xmlhttp.responseText)
var xmlDoc=xmlhttp.responseXML.documentElement;
}
}
getFlickr();
</script>

The cool thing about JSON is that it's actually executable code. You don't need to do any "manual" parsing – just run the code. Perhaps Flickr supplies a function called jsonFlickrApi with their API libs that they exepct you to use, but you could just as well supply your own.
function parseFlickrJson(jsonstring){
var data=null;
var jsonFlickrApi=function(d){
data = d;
}
eval(jsonstring);
return data;
}
myreturndata = parseFlickrJson(response);
// Try getting something from the object
alert(myreturndata.photos.pages);

Related

Export To Excel from Asp Net Web API Controller

I am working on New web application which is Using Web API as Business Layer and Knock out Js as client side frame work to binding. I have a requirement like Pass the certain search criteria to Web API Controller and get the Data from DB and Create and Send the Excel/MS-Word file on the fly as a downloadable content.
I am new to both the Web API and Knock out, I am searching on the Net and get partial solution and I am looking here to get more optimal solution for this use case.
Below is my code:
Client:
function GetExcelFile() {
var $downloadForm = $("<form method='POST'>")
.attr("action", baseUrl + "api/FileHandler/GetExcelFileTest")
.attr("target", "_blank")
$("body").append($downloadForm);
$downloadForm.submit();
$downloadForm.remove();
}
On Button Click having this code snippet to create a form on the fly and Get response from Web API.
Web API Code:
[HttpPost]
public HttpResponseMessage GetExcelFileTest()
{
var response = new HttpResponseMessage();
//Create the file in Web App Physical Folder
string fileName = Guid.NewGuid().ToString() + ".xls";
string filePath = HttpContext.Current.Server.MapPath(String.Format("~/FileDownload/{0}", fileName));
StringBuilder fileContent = new StringBuilder();
//Get Data here
DataTable dt = GetData();
if (dt != null)
{
string str = string.Empty;
foreach (DataColumn dtcol in dt.Columns)
{
fileContent.Append(str + dtcol.ColumnName);
str = "\t";
}
fileContent.Append("\n");
foreach (DataRow dr in dt.Rows)
{
str = "";
for (int j = 0; j < dt.Columns.Count; j++)
{
fileContent.Append(str + Convert.ToString(dr[j]));
str = "\t";
}
fileContent.Append("\n");
}
}
// write the data into Excel file
using (StreamWriter sw = new StreamWriter(fileName.ToString(), false))
{
sw.Write(fileContent.ToString());
}
IFileProvider FileProvider = new FileProvider();
//Get the File Stream
FileStream fileStream = FileProvider.Open(filePath);
//Set response
response.Content = new StreamContent(fileStream);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/ms-excel");
response.Content.Headers.ContentLength = fileStream.Length;
//Delete the file
//if(File.Exists(filePath))
//{
// File.Delete(filePath);
//}
return response;
}
Using this code I am able to download an Excel File. Still I have some more open questions to make this code optimal.
Q1) I need to Pass view model(Search Criteria) to API Controller Using the dynamically create form ? (OR) Any better ways to get Excel file from Web API.
Q2) I am sure it's not a good way to create Excel file in Physical folder and Get FileStream and send as a respone. How to do on the fly ? OR any other optimal ways.
Please suggest me to do better ways.. Thanks
Q1) You can quite easily pass the view-model, but it's also similarly easy to pull that information from the posted form.
Passing the view-model
If you want to pass the view-model to a WebAPI method then remember that said method must take as a parameter an object with the same properties. So if the object that you wish to post back always has the same properties then it's trivial to build a server-side class with the same properties and receive an instance of that class.
To post back this client-side object you can do something like this (uses jQuery, which I see you're already using):
$.ajax({
contentType: "application/json",
data: my-view-model.toJSON(),
type: "POST",
url: baseUrl + "api/FileHandler/GetExcelFileTest" });
I haven't attached any success or error handlers here because the JavaScript isn't concerned with the return, but you might wish to add some handlers in case an exception is thrown in your WebAPI method. I recommend doing that by adding the following to the above $.ajax() call:
statusCode: {
500: function(jqXhr, textStatus, errorThrown) {
},
[other HTTP error codes]
}
[Read the documentation for the $.ajax() call here.]
One additional tip here: when you call my-view-model.toJSON() (or self.toJSON(), if called from within your view-model) Knockout will first of all determine if your view-model contains a toJSON() method. If so, it will use this method; if not then it will call the browser's implementation of this function. However, the browser's implementation of this function will serialise everything, which can be particularly length if you have, for example, long select lists in your view-model. Therefore, if you wish only to send back a subset of the view-model's properties then define your own toJSON function on your view-model like so:
var toJSON = function() {
return {
Property1: ...,
Property2: ...
};
}
[Read more about converting a view-model to JSON here.]
Posting the form as-is
If you don't wish to expend the effort to do the view-model wiring then you can just post the form exactly like you have in your question. You can then retrieve the values from the form by using
Request.Form["my-field"];
Q2)
You're probably right in pointing out that it's not wise to create the Excel file in the physical folder. However, as far as I'm aware (interested if someone says otherwise) you'll have to use a 3rd-party library for this. Microsoft do offer an Office automation library but I have a suspicion that you also need Office to be installed at the same location.
Creating Excel spreadsheets dynamically is something I've done several times but for the actual creation I use Aspose.Cells, which requires a license. Although I do create a physical version and then delete it, I believe Aspose.Cells may allow you to create it as a stream. But take a look around, there are certainly other libraries which offer Excel automation.
Returning the File from the Server
Calling $.ajax({...}) alone won't allow you to present the user with a "Save as..." dialog. What I do in this situation - and this won't work if you wish to store the generated file only in memory (FileStream, for example) and not on the file system - is to respond to the $.ajax({...}) call with a filename for the generated file.
The next step is to direct the user towards that filename.
So I have something like this in my JavaScript:
$.ajax({
dataType: "json",
type: "GET", // you'll probably want POST in your case
url: ...,
success: function(response) {
if (response && response.Uri && response.Uri.length) {
window.location.href = [root URL] + response.Uri;
}
}
});
But don't be alarmed by this redirect. That window.location.href points directly to a folder on the server, no controller needed. Because the browser then receives a file it presents the "Save as..." dialog while remaining on the same webpage.

GWT FormPanel method replaced by input parameter

We've discovered a strange new bug in a GWT application I'm maintaining, and I'm not sure when it became an issue. Possibly with a new Firefox version.
We're sending a POST request to the server using a FormPanel, essentially like many examples I've seen online. But since we actually want a PUT request, one of the hidden input parameters is named "method" and has a value of "put".
Now, when I look at the request in Fiddler coming from Firefox, it is being transformed into a GET request with all the parameters in the QueryString. In IE and Chrome, the parameters are in the body of a POST request.
I've displayed the value of FormPanel.getMethod() in an alert, and in IE and Chrome the string "post" is displayed, whereas in firefox it is showing "object HTMLInputElement". Unfortunately, hosted mode debugging does not work with this project.
It obviously looks like the FormPanel's getMethod() function is returning the hidden input parameter named method instead of the actual form's method in Firefox.
Technically I should avoid changing the servlet as this is from an OpenSource project that we use, though I've found I can fix the issue by changing the hidden input parameter's name to "_method" on both ends.
Has anyone ever seen anything like this? I can't find anything in Google.
UPDATE: We're using GWT 2.3 in case that helps
Some insight can be found here Are the PUT, DELETE, HEAD, etc methods available in most web browsers?
I would also suggest using XMLHttpRequest. In this case you [most probably] don't have to change anything on the server side.
In case if you use Submit button, you can write in its clickHandler function:
submitMyForm(yourTextBox.getText(), self);
// self - is the instance of main class (named UploadForm here), needs to be passed here for future reference
and then some more (you can adapt this for your needs):
private native void submitMyForm(String text, UploadForm handler)/*-{
var fd = new FormData();
fd.append("textValue", text);
var xhr = new XMLHttpRequest();
var upload = xhr.upload;
readyStateChangeHandler = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var serverResponse = eval(xhr.responseText); // optional
handler.#com.project.UploadForm::onUploadIsDone(Lcom/google/gwt/core/client/JavaScriptObject;)(serverResponse);
} else {
handler.#com.project.UploadForm::onUploadFailed(I)(status);
}
}
};
xhr.onreadystatechange = readyStateChangeHandler;
xhr.open("PUT", yourActionUrlHere);
xhr.send(formData);
}-*/;

json/ajax confusion

I've got a response that sends back an entire table. N number of rows with 7 cells in each row. So I end up with nX7 responses. Apparently, I should be using JSON to handle the string appropriately. I've found tutorials on how to create a JSON object, but not so much on how to send it via ajax and how in sending it through ajax, the jsp knows to fill the JSON object with the responses... In other words,
I create JSON object in javascript (check)
place JSON object in the ajax code (confused)
response with JSON object filled (confused)
Parse JSON object so I can get at the data easily (maybe confused, we'll see after steps 2/3)
I am not using jquery as I'm still learning and jquery's syntax is confusing currently.
var sweekStart = document.getElementById("weekStart").value;
var smonth = document.getElementById("month").value;
var syear = document.getElementById("year").value;
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "empTableRepop.jsp?weekStart=" + encodeURIComponent(sweekStart)+"&month="+encodeURIComponent(smonth)+"&year="+encodeURIComponent(syear);
xmlhttp.open("POST",url,true);
//alert("made it to open");
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
//alert(xmlhttp.responseText);
var test = xmlhttp.responseText;
reFillTable(test);
}
}
xmlhttp.send(null);
The variable "test" (yea, bad name but it's temporary) is the object I want converted from a standard var to a JSONobject. If I understand correctly, JSON will already have the string parsed when it receives the response. I realise I can change "function()" to be directly "reFillTable(test)" but given the path it took me to get it working I ended up with that somehow lol. Will fix once everything is working properly.
EDIT:
This is how I "display" the information from the jsp/java file.
//Name Cell
out.println(empName);
//Mondays Hours
out.println(hoursArr[0]);
//Tuesdays Hours
out.println(hoursArr[1]);
//Wednesdays Hours
out.println(hoursArr[2]);
//Thursdays Hours
out.println(hoursArr[3]);
//Fridays Hours
out.println(hoursArr[4]);
//Total hours Cell
out.println(PTOAmt);
Assuming that your serverresponse is already working, this gives you the JavaScript object from the received JSON.
var test = JSON.parse( xmlhttp.responseText );
To clarify: There is no explicit "JSONObject" in JavaScript. JSON stands for JavaScript Object Notation and is simply a shorthand for writing normal JavaScript objects. It became, however, popular as a means of serializing data to send through AJAX-request.
In the end the server just sends a string in JSON format, which you on the other hand have to parse again (by JSON.parse()) in order to have an object representing the data send.
Just to add: JSON.stringify() is the operation in the other direction. Creating a string out of a JavaScript object.
With respect to the edit:
As said in the comment, this does not create valid JSON (have a look # json.org for an overview).
So now you have some choices:
Use a library like GSON to encode your data.
Parse your data by hand in JavaScript. (I would not recommend this).
Create a valid JSON string manually.
The code for the third option, may look like this:
// start the JSON object
out.print( "{" );
//Name Cell
out.println( "\"empName\":\"" + empName + "\"," );
// start an array for the next few values
out.print( "\"hours\": [" );
out.print(hoursArr[0] + "," );
out.print(hoursArr[1] + "," );
out.print(hoursArr[2] + "," );
out.print(hoursArr[3] + "," );
out.print(hoursArr[4] + "," );
// end the array
out.print( "]," );
//Total hours Cell
out.print( "\"PTOAmt\":\"" + PTOAmt + "\"");
// end the JSON
out.print( "}" );
This assumes that PTOAmt is a string as well.
On the long run you should use a library like mentioned in option (1) to handle the encoding.

Greasemonkey: using XPath to get elements from distant XML-document

What Im trying to do with my Greasemonkey script is:
to read some distant XML document;
convert it into XML object;
and then use XPath to get the elements inside of it.
The getElementsByTagName(TagName) method works fine with my XML-object, but evaluate("XPath expression") doesn't. Any suggestions? See the code below:
GM_xmlhttpRequest({
method: "GET",
url: "http://www.someserver.com/atom.xml",
onload: function(response) {
if (!response.responseXML) {
var xmlDoc = new DOMParser().parseFromString(response.responseText, "application/xml");
}
// this section works fine and returns the data of the first <entry>..</entry>
var snapEntries = xmlDoc.getElementsByTagName("entry");
alert (snapEntries[0].data);
// this section doesn't work for unknown reason and returns nothing
var snapEntriesXpath = xmlDoc.evaluate("//entry", xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
alert (snapEntriesXpath.snapshotItem(0).data);
}
});
IIRC, the .data attribute won't be present for every kind of search.
You probably need to use:
var snapEntriesXpath = xmlDoc.evaluate (
"//entry//text()", xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null
);
But several other issues could be at play. If that doesn't do it, (1) link to the exact XML file; use pastebin.com if necessary. (2) Report what Firefox's error console (CtrlShiftJ) reports.

With JavaScript Ajax polling for widget

I have the follow problem. I need to create a JS widget and set it on one blog, for example any blog from blogger.com. YOu can select there a box for javascript and I will post the JS in this box.
The problem what I have and don't know how to do this is, that the script should do an ajax polling for exmaple for 60 seconds. But how to execute an ajax call, when the host is not the same linke the host, where the JS is includet?
For example the easiest way to explai is: There is a search box and when enayone searches for anythign, then the JS script should streaming the results for 60 seconds from the server what I have set in the script and is different as the host, where the JS is includet, without to become a problem with the JS restriction for hosts.
Or for example a chat client, where the client is hosted on one other host and the server on another.
Can anyone tell me an idea, or send me an example how to do this?
Thanks
Nik
Well with this example is it possible but without JSONP?
function asyncreq(url) {
var xmlhttp = false;
try {
xmlhttp = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xmlhttp = false;
}
}
}
if (xmlhttp){
try {
xmlhttp.open("GET", url);
xmlhttp.onreadystatechange=function() {
document.getElementById('mydiv').innerHTML = xmlhttp.responseText;
}
xmlhttp.send(null);
}
catch (failed) {
xmlhttp = false;
}
}
}
If you send the response in chunks, then everything is fine. But here is the call in ajax again. And when I use it in a different host, then I can't call the url because of the same-origin policy.
Is there another way?
I found a very interesting example here.
Take a look at the bottom, there is a job search box. If you investigate a litte bit, then you will see there is a usage of a class RSL() which is doing the request. How this class is doing the request without ajax? I can't understand wow this class works. Can anyone show me a better example?
There are two main options:
Put an iframe where you want the widget to go. Its src URL would be on the same server that will receive the AJAX call.
Use JSONP, which consists of inserting a script tag into the page to bypass the same-origin policy. This requires that the AJAX server wrap its JSON output in ?(...), where the URL includes callback=?. Then, as soon as a response has been received, start another request.

Resources