I have a simple ASP.NET web application with the following javascript that runs on an input's onblur event:
function checkUserName() {
var request = new XMLHttpRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = encodeURIComponent(theName);
var url = "Default.aspx/CheckName?name='" + theName + "'";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.send();
}
}
The C# method this calls is the following:
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static string CheckName(string name)
{
return name + " modified backstage";
}
The javascript callback for the XMLHttpRequest is the following:
function createStateChangeCallback(request) {
return function () {
if (request.readyState == 4) {
var parsed = JSON.parse(request.responseText);
alert(parsed.d);
}
}
}
Although this displays the results of my server-side method, I was wondering about that property "d" I need to access to get the results. I found this only by using Intellisense. Is this property a standard property for accessing the parsed JSON? Should I be going about it some other way? Is "d" arbitrary or is it determined somehow? Is it possible for me to set the name of the property, either client or server -side?
Regarding the following:
var parsed = JSON.parse(request.responseText);
alert(parsed.d);
d is an actual property from the response object sent from the server via the GET request. It's not a special property created from the JSON.parse() method.
The server is likely wrapping the return data object into d. Thus, the response object looks something like { d: stuff } where stuff is the data that is returned.
--EDIT--
After a little digging on this, ASP.NET and WCF endpoints format the JSON object into the d property to prevent CSRF and XSS attacks. For more info, visit http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/.
.d is added by ASP.NET in framework code under the System.Web.Extensions namespace, and it's hardcoded, so no, you can't change it unfortunately. It exists to mitigate XSS attacks. On the plus side, however, you can count on .d always being present.
Nope. Afraid not the standard xmlhttprequest object is designed for XML/HTML so you will need to parse the json from the raw text I'm afraid.
The new XHR2 spec does handle additional response types though (if your browser supports it mimd).
http://www.html5rocks.com/en/tutorials/file/xhr2/
Related
I'm trying to write a JavaScript function that gets a foreign url, and attempts to verify its existence within 'tmOut' msecs. If verified within this timeframe, it should call a 'callback' function with this url as an argument.
Here is the function:
function chkUrl(url, tmOut, callback) {
var abortChk = false;
var abortTmr = setTimeout(function(){abortChk = true;}, tmOut);
var x = new XMLHttpRequest();
x.onreadystatechange = function() {
if (x.readyState == 4) {
if (x.status < 400 && !abortChk) {
clearTimeout(abortTmr);
callback(url);
}
}
};
x.open('GET', url, true);
x.send(null);
}
Problem is because of cross-domain calls (probably) I get x.status=0 regardless of the url existence.
Is there a way to overcome/workaround the problem (without the users having to modify any default browser settings)? Alternatively, is there a way to achieve the same functionality otherwise?
Is this function "reentrant"? (can I call it safely several times for different urls at once?)
Is there a way to overcome/workaround the problem
Client side? Only if the sites you are making the request to use CORS to grant you permission (which seems unlikely given the context).
Perform your test from your server instead of directly from the browser.
Is this function "reentrant"? (can I call it safely several times for different urls at once?)
Yes. You aren't creating any globals.
I want to send by XMLHttpRequest a JSON object to a Perl Script (*.cgi)
But I can't decode the JSON object in the cgi file.
I always reveive the error message:
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before
"(end of string)")
This is my javascript code:
//ajax communication for receiver/transceiver
function doAjaxRequest(query)
{
if(whatReq == "")
{
alert('ERROR: Request-Type undefined');
return;
}
if (window.XMLHttpRequest)
{
arequest = new top.XMLHttpRequest(); // Mozilla, Safari, Opera
}
else if (window.ActiveXObject)
{
try
{
arequest = new ActiveXObject('Msxml2.XMLHTTP'); // IE 5
}
catch (e)
{
try
{
arequest = new ActiveXObject('Microsoft.XMLHTTP'); // IE 6
}
catch (e)
{
alert('ERROR: Request not possible');
return;
}
}
}
if (!arequest)
{
alert("Kann keine XMLHTTP-Instanz erzeugen");
return false;
}
else
{
var url = "****.cgi";
var dp = document.location.pathname;
arequest.open('post', url, true);
arequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
//receiver function
arequest.onreadystatechange = function()
{
switch (arequest.readyState)
{
case 4:
if (arequest.status != 200)
{
alert("Der Request wurde abgeschlossen, ist aber nicht OK\nFehler:"+arequest.status);
}
else
{
var content = arequest.responseText;
analyseResponse(content);
}
break;
default:
//alert("DEFAULT:" + arequest.readyState );
break;
}
}
//transceiver function
query="jsonObj=" + JSON.stringify({name:"John Rambo", time:"2pm"});
alert(query);
arequest.send(query)
}
}
And here the cgi file:
#!/usr/bin/perl
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser);
use strict;
use warnings;
use JSON;
use Data::Dumper;
my $jsonObj = param('jsonObj');
my $json = JSON->new->utf8;
my $input = $json->decode( $jsonObj );
print Dumper(\$input);
Can you help me? I don't know how to access the JSON object.
Thank you very much.
This message says you've got non-JSON string in $jsonObj. One particulary common case is empty string. Try printing out raw content of $jsonObj and make sure you set up everything correctly for CGI::param to work and also check with browser's built in tools that it actually sends data.
Also I highly suggest you throwing away 10 years old ActiveX shit. You're using JSON.stringify and all the browsers that support it also support native XMLHttpRequest.
I was about to vote to put your question on hold because of insufficient information to reproduce and diagnose the problem, but then I realized that your question does contain enough clues to figure out what's wrong — they're just really well hidden.
Clue #1: Your error message says (emphasis mine):
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)")
This implies that your $jsonObj variable has length 0, i.e. it is empty.
So, what's causing it to be empty? Well, the Perl code looks like perfectly standard CGI stuff, so the problem must be either in your JS code, or in something that your haven't showed us (such as your web server config). Since we can't debug what we can't see, let's focus on your JS code, where we find...
Clue #2: There's something wrong with this line:
arequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
Of course, you can set any content type you want for a POST request, but CGI.pm expects to receive the content in one of the standard formats for HTML form submissions, i.e. either application/x-www-form-urlencoded or multipart/form-data. When it receives something labeled as application/json instead, it doesn't know how to parse it, and so won't. Thus, the param() method in your Perl script will return nothing, since, as far as it's concerned, the client sent no parameters that it could understand.
There should have been a warning about this somewhere in your web server error logs, but you presumably didn't think to check those. (Hint: you really should!)
(You could've also used the warningsToBrowser option of CGI::Carp to get those warnings sent as HTML comments, but I guess you weren't aware of that option, either. Also, to make that work reliably, you'd really need to use CGI::Carp before the CGI module, so that it can catch any early errors.)
Anyway, the fix is simple: just replace application/json in your JS code with application/x-www-form-urlencoded, since that's what what you're actually trying to send to the server. You should also make sure that your JSON data actually is properly URL-encoded before embedding it in the request, by passing the output of JSON.stringify() through encodeURIComponent(), like this:
var data = {name:"John Rambo", time:"2pm"};
var query = "jsonObj=" + encodeURIComponent(JSON.stringify(data));
(I'll also second Oleg V. Volkov's suggestion to get rid of all the obsolete ActiveX stuff in your JS code. In fact, you could do even better by using a modern JS utility library like, say, jQuery, which provides convenient wrapper functions so that you don't even have to mess with XMLHttpRequest directly.)
I am looking at a scenario where I want to "consume" an xml/json document and build some visual elements from said date.
Per example, List of bookings for a time period. Lets say data will contain
<unit>
<booked>
<pic>
<booked range>
What I am not sure of, is how to go from accessing a query string, to catching the returned xml. This seems simple, but I cant seem get get my head around accessing the XML returned, from Javascript.
More info:
I am building a mobile app, that will display data, retrieved from XML. (I want to run the url/query string from the app, to generate a custom xml doc, and read XML data returned (not display the web page)
Any advice?
Synopsis
Collect the xml through an ajax call.
Xml response available as dom tree (parsed) or in lexical representation (text)
Have the callback handler process your xml and interact with the dom
options to process your xml:
XPath
Xslt
DOM functions
string manipulation
string parsing ( probably pointless, unless you have special requirements on parsing )
Code
A pure Javscript solution using the XMLHttpRequest ( docs: eg. MDN reference, MDN usage hints; there also exists a tutorial on html5rocks ) might look similar to the following fragment:
var oReq = new XMLHttpRequest();
function eh_onload ( ) {
var xmlhttp = this;
if (xmlhttp.readyState === 4) {
console.log ( "xmlhttp.status = " + xmlhttp.status);
if (xmlhttp.status === 200) {
//
// process your xml here.
//
console.log ( "responseText = '" + xmlhttp.responseText + "'");
console.log ( "xml root element = '" + xmlhttp.responseXML.documentElement.nodeName + "'");
}
else {
console.log('error');
}
}
}
oReq.onload = eh_onload;
oReq.open("get", "http://wsearch.nlm.nih.gov/ws/query?db=digitalCollections&term=cholera", true);
oReq.send();
The code snippet performs an ajax request and registers a callback that will be executed upon completion of the request. As you can see, you may either access the lexical representation of the xml data received or a parsed DOM structure.
Alternative
In case using the jquery library is acceptable to you, you may proceed along the lines of the following code sample:
function eh_xml ( parsedxml, textStatus, jqXHR ) {
// process your xml here.
//
console.log ( "typeof(parsedxml) = '" + typeof(parsedxml)+ "'");
console.log ( "$('term', parsedxml).length = " + $("term", parsedxml).length);
}
$.ajax({
url: "http://wsearch.nlm.nih.gov/ws/query?db=digitalCollections&term=cholera"
, dataType: "xml"
, success: eh_xml
});
The code snippet performs an ajax request and provides a callback that receives the xml in parsed (DOM) representation.
Note & Caveat
The code sample uses a public web service provided by the US NIH returning xml data. This one has been selected randomly and is employed for the sole purpose to have a working PoC. No affiliations exist and the usual legal disclaimers apply.
The code can be tested from the console (eg. in Chrome) opened on the site http://wsearch.nlm.nih.gov/ using the following prelude which loads the jquery library in the context of the site hosting the web service:
var script = document.createElement("script");
script.src = "http://code.jquery.com/jquery-2.1.3.js";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
I have found a geocoder website that will give me some data that I need as a variable in my javascript code: http://geocoder.us/service/csv/geocode?zip=95472. the website returns only the content: 38.393314, -122.83666, Sebastopol, CA, 95472. I need pull this information from the website and put it into a string.
abc = "38.393314, -122.83666, Sebastopol, CA, 95472"
How can I accomplish this?
You can use AJAX:
var req = new XMLHttpRequest(); //Create an AJAX object
req.open('GET','http://geocoder.us/service/csv/geocode?zip=95472',true); //Location and method
req.send(); //Send
req.onreadystatechange = function() { //When it's ready
if (this.readyState === 4) { //... which is code 4
console.log(this.responseText); //Then you have the responseText
}
}
This only works when the request is from the same domain, tho (for security purposes). If you want it to work on any domain, you'll have to use a proxy.
You should use Javascript to make an ajax request to that URL and it will return the information you want in a format you specify, usually JSON. Depending on what Javascript libraries you are/aren't using, there's different ways you could do that -- probably the most common would be to use jQuery to make your request. Here's info on that API:
https://api.jquery.com/jQuery.get/
I want to make a little web page which calculates stuff, based on various data from another site. Let's say for an online browser game.
I would like to have it take some specific details from the web pages on the game, but I don't even know where to start.
Is this doable with javascript (if not I would like to know with what language it is)? Could anyone give me a general of guideline of how this can be done?
You can use a combination of AJAX and XMLHTTPRequest, but these are subject to the same origin policy.
Of course, it would make it a lot easier if the external site can send back data in JavaScript Object Notation format (JSON) for readability.
There is a similar question asked here for how to obtain the contents of an external site using XMLHTTPRequest here: How to specify an external website for XMLHTTPRequest
There is another similar question on using XMLHTTPRequest and JSON: Cross-domain JSON request?
I have a standard function for using AJAX to get information dynamically. I use PHP as my listener. Your listener would have to be able to accept variables from the URL, like PHP $_GET[].
In the example below, your listener named "source_url.php" would have to check the values received in $_GET[field] and then simply print/echo the result.
JAVASCRIPT:
function get_(url, func)
{
var http;
try { http = new XMLHttpRequest(); } catch (e) { try { http = new ActiveXObject(\"Msxml2.XMLHTTP\"); } catch (e) { try { http = new ActiveXObject(\"Microsoft.XMLHTTP\"); } catch (e) { alert(\"Your browser broke!\"); return false; } } }
http.open(\"GET\", url, true);
http.onreadystatechange = function() { if(http.readyState == 4) { func(http); } }
http.send(null);
}
function get_info(fieldname)
{
get_("source_url.php?field=" + fieldname, showResult)
}
function showResult(h)
{
alert("The result is: " + h.responseText);
}
HTML
<button onClick='get_info("name");'>Get the ship Name</button>
<button onClick='get_info("reg");'>Get the Registration Number</button>
<button onClick='get_info("capt");'>Who is the Captain?</button>
PHP
<?php
if ($_GET[field] == "name") { print "U.S.S. Enterprise"; }
if ($_GET[field] == "reg") { print "NCC - 1701"; }
if ($_GET[field] == "capt") { print "Jean Luc Picard"; }
?>
I use this all the time, though I have created a more advanced version with authentication security. This is where you should start if you are just learning how AJAX works.