Beruflich Dokumente
Kultur Dokumente
JSON in ASP.NET Ajax: First words
Posted on Monday, October 22, 2007 2:49 AM
If you are a web developer, and you haven't been living under a rock for most of the past year, you must at least have
heard of JSON. In the wake of the tremendous hype relating to everything even vaguely AJAXrelated, JSON has
climbed in record time the list of the top 10 technologies a web developer has to master.
Let's make it clear from the start: JSON does deserve a top spot in such a list, if nothing else because it's the skeleton
that keeps the whole AJAX paradigm on its feet. Even more so for us .NET programmers. In fact, we'd be more
accurate if we called it AJAJ, although I agree that would feel quite stupid . As a matter of fact, when using
ASP.NET AJAX, most of the communication between client and server is serialized in JSON format rather than XML,
at least when using the default settings. And there's good reason for that.
In fact, JSON is a very simple humanreadable, easilyparsable datainterchange format, like XML, but unlike the
latter, it is very concise, and, more importantly, it is immediately convertible to a Javascript object. That is, if you
simply eval() a JSON expression, you get returned the actual object that was serialized in the first place.
For those of you who might not know it, eval() is a builtin javascript function that evaluates a string and executes it as
a line of code (see here for more info).
For example, you might serialize a very simple "Person" object that has properties "firstName", "lastName", and "age"
as follows:
{"firstName":"Marco","lastName":"Anastasi","age":27}
Note that property names are always enclosed in double quotes, while values follow the usual javascript syntax.
In Javascript, you would then be able to use code like this:
alert(person.firstName);
Note that we enclose the json expression we are evaluating in parentheses, to instruct eval() to treat the string as an
expression rather than a block of code.
WARNING: what you see here is merely used as an example. You should avoid resorting to the eval() function in a
production environment, because of potential security breaches. There are valid alternatives out there, and a good
place to start looking for them is, of course www.json.org.
In my next posts I'll talk profusely about one of the possible solutions to this problem (and probably the one that
ASP.NET developers are keener to use), i.e. ASP.NET AJAX's builtin client side JSON serializer/deserializer.
What you've seen so far is obviously a very simplified introduction to JSON, and doesn't show much of what you
might achieve by leveraging its power and simplicity. In my next post, I'll delve deeper into its inner workings and how
to use it to manage the communication between client side script and a serverside application, and finally to retrieve
information from web services, shape it into different formats and serve it to the client browser.
<< JSON in ASP.NET Ajax: First words | Home | Data Interpolation with SPLINE in C# >>
JSON in ASP.NET Ajax: Part 2. Calling a remote JSON Web
Service from client script
Posted on Wednes day, October 24, 2007 2:00 AM
Now, after the very futile example which accompanied the introduction to JavaScript Object Notation in my last post
(by the way, I forgot to mention that this is what the fancy acronym stands for, but I'm sure you already knew that),
let's go straight to the fun part, and see how we can leverage the flexibility of JSON (and ASP.NET AJAX, of course)
to achieve some less trivial result. When developing a web application, we often need to aggregate data from different
sources. You might argue this is no big news, as we've all used web services in a way or the other, and "mashup" is
surely not an uncommon word these days. But probably, for most of us, the natural way to think of data returned from
a web service call is XML. But XML is not exactly the easiest thing to parse on the client, nor a very succinct format.
That's why a number of JSON web services have flourished lately. Probably the first that comes to mind is Google
Maps' Geocoder (see here), but there are a lot more. If you are looking for inspiration you can have a look at
xmethods. But today, we are focusing on some very, very interesting web methods kindly offered by Geonames.
In fact, as I've always mantained that an example is worth a googolplex words, in this post I'm going to describe a
specific problem I had to solve recently, and the rather simple solution I found, using JSON and ASP.NET AJAX.
So, let's get this started: enter
The Problem.
Let's imagine we want to retrieve the most recent weather information for a specific location, given its geographic
coordinates. In particular, let's imagine that we let the user input the coordinates directly on the client (for example by
clicking on a Virtual Earth map) and we want to visualize the latest weather data observed at the nearest weather
station, avoiding the user the annoyance of the much dreaded postback.
The Solution.
Luckily, the findNearByWeatherJSON web service at Geonames does exactly what we need. It takes a longitude and
latitude as parameters, and returns a JSON object describing the weather conditions gathered at the nearest
observing site.
Although you could directly call this service from the client using classic AJAX patterns (see here for a simple
example or have a look at ajaxpatterns), we'll focus on how to do that by using a proxy ASP.NET web service to avoid
security problems and allow for more flexibility, and, as a nice bonus, have more readable and maintainable code. In
fact, rather than following a RESTful approach, and call the web service directly from javascript, we'll leverage the
ASP.NET AJAX infrastructure and use the more concise and readable RPCstyle generated for us by the framework.
But the question is: how? When faced with the necessity to create a serverside proxy for a remote JSON service,
one might be tempted to try and find something like the "Add Web Reference" wizard Visual Studio has been spoiling
us with for years... well, no luck this time, there's nothing like that for JSON. In fact, while the wizard would help us if
we had to consume a SOAP web service, there's nothing like WSDL which can describe the results and help
generate a proxy class for JSON services.
But the good news is, we don't need any! In fact, unless you want to elaborate in some way the results returned from
the web service (and I'll cover that topic in one of my next posts), all you need to do is create a simple local ASP.NET
web service whose only duty, when called, is to make a request to the remote web service and forward the result to
the client. So, let's see how to implement all this!
First of all, let's see how to implement the ASP.NET proxy web service:
using System;
using System.Web.Script.Services;
using System.Web.Services;
namespace Mashup
{
/* To allow this Web Service to be called from script using ASP.NET AJAX,
[ScriptService]
[WebService(Namespace = "Mashup")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[WebMethod]
You can see that the web service we're publishing takes two parameters, latitude and langitude of a location, and
returns a string. We'll see that this string is going to contain exactly the content of the response received from the
Geonames Web Service. What we have to notice now, is that we decorated the WeatherService class with the
[ScriptService] attribute. This is all we have to do to instruct the ASP.NET engine to create a Javascript helper class
that will let us call this method very easily from client code.
NOTE: If you want to have a look at what the generated Javascript proxy class looks like, all you have to do
is requesting the .asmx web service from your browser, and append /js to the url. (e.g.
http://localhost:2687/JsonTest/WeatherService.asmx/js)
Now, let's delve deeper into the implementation of the GetWeatherByLocation() method:
using System;
using System.Net;
using System.Globalization;
using System.IO;
namespace Mashup
"http://ws.geonames.org/findNearByWeatherJSON?lat={0}&lng={1}";
jsonResponse = sr.ReadToEnd();
return jsonResponse;
return (HttpWebRequest)System.Net.WebRequest.Create(serviceUri);
service in a RESTful manner, retrieve the response, write it into a string and finally return the string to the caller
method. The response returned from the findNearByWeatherJSON service will be something like this:
"{"weatherObservation":{
"clouds":"few clouds",
"weatherCondition":"n/a",
"windDirection":290,
"ICAO":"LICC",
"elevation":17,
"countryCode":"IT",
"lng":15.05,
"temperature":"16",
"dewPoint":"7",
"windSpeed":"09",
"humidity":55,
"stationName":"Catania / Fontanarossa",
"datetime":"2007-10-23 17:20:00",
"lat":37.4666666666667,
"hectoPascAltimeter":1009 }}"
NOTE: Carriage returns have been inserted only to improve readability, but the response stream won't
contain any.
The similarity between this string and a Javascript object is quite evident. We'll see in a moment how to leverage this
not so coincidental fact.
Now, our server infrastructure is almost complete. The last step we have to take is referencing the Web Service we
just created from the page that is actually going to use it.
To do this, we simply add a ScriptManager to the page, and add a reference to the web service in its <Services>
section:
<Services>
</Services>
</asp:ScriptManager>
Now we can start to set up a very simple test page to try our flaming new web service!
For now, we'll only add a couple of textboxes to input latitude and longitude, and a button to start the Web Request.
We'll do it AJAX style, so we'll use the HTML controls rather than their heavier ASP.NET counterparts. We'll also add
a div where we're going to visualize the weather info retrieved from the web service. Note that we are giving id's to all
the controls so that we can reference them from the Javascript code that we are going to write.
<div id="divResult">
</div>
Now all that's left to do is write the Javascript code to wire up everything.
We'll start by implementing the callService() function that will be fired when clicking on the button. Please note that in
a real scenario, clicking the button would trigger some sort of validation of the input data. We won't do any of that
here in order to keep the code as simple and streamlined as possible.
function callService() {
Mashup.WeatherService.GetWeatherByLocation(latitude, longitude,
GetWeather_success, onFailed);
Let's see what we are doing here. First of all we are creating two variables, latitude and longitude, which contain the
value of the two textboxes.
NOTE: Those of you who haven't put their hands on the client side ASP.NET AJAX library yet, might wonder
what the $get function does. Actually, not much, except sparing you some keystrokes, as it is a mere
shortcut for the Javascript getElementById function. In particular, when called passing only one
parameter, the $get alias resolves to document.getElementById, while when called like this: $get(id,
us care of the ASP.NET AJAX framework. As you can see, we can find our WeatherService.GetWeatherByLocation()
method inside the Mashup namespace. Please note we have to use the fully qualified name to invoke the service.
Besides the two parameters defined in the web method signature in the server side code, we see that the generated
Javascript method takes some additional parameters: onSuccess, onFailed and userContext. As you have probably
already realised, they take the name of two callbacks, one that will be executed upon successful completion of the
remote method invocation, the other that will be called in the unfortunate event something went wrong. The third
parameter, which we are not using here, would let you pass a custom user context to the callback.
Now, if everything works as expected, the GetWeather_success function will be called (asynchronously) when the
web service response is ready, and will get as an argument the web method's return value, in our case, a string
containing our JSONserialized weather observation object.
Now the very last thing we need to do is deserialize such string into a real Javascript object. To do that, we might
simply call the Javascript eval() function, as I anticipated in my previous post:
function GetWeather_success(e) {
var line;
result.weatherObservation[property]); weatherData.append(line);
$get('divResult').innerHTML = weatherData.toString();
function onFailed() {
As I just said, when this function is called, it is passed the web method response, thus e contains the JSON
representation of a Javascript object containing all the relevant weather data retrieved from our remote Web Service.
As you can see, calling eval() deserializes the string and returns an object we can readily use.
From now on, what we are going to do with this native Javascript object is entirely up to us. Here, as a mere example,
I'm enumerating all its properties and displaying them inside the div we created for this purpose.
What's worth noting here is the use of two very interesting and useful ASP.NET AJAX features: the
Sys.StringBuilder class that mimics its serverside homonym and greatly improves string concatenation performance
over the "+" overload, and the String.format() function, which endows Javascript with the very useful .NET
String.Format() method we are all used to.
For those of you concerned with security, as I said earlier, eval() is probably not the safest option to deserialize JSON,
so you might decide to resort to a JSON parser (you can find one here on json.org), or once again leverage the power
of ASP.NET AJAX, by using the builtin JavaScriptSerializer. If you simply substitute the first line in
GetWeather_success() with the following line:
the string returned from the web method will be checked against a regular expression to ensure it is actually a valid
JSON string.
Well, that's all for now! I hope that this short introduction to the use of JSON with ASP.NET has been useful to some
of you!
showing current weather conditions on a map >>
JSON in ASP.NET Ajax: Part 3. Server side deserialization and
elaboration of JSON data returned from a Web Service.
Posted on Wednes day, October 31, 2007 6:32 PM
This is the third part of a series of articles on ASP.NET AJAX and JSON. If you haven't read part 1 and part 2 of this
series, you are strongly advised to do so before going on to read this article.
Let's take what we've seen so far on JSON and ASP.NET one step further, and discover how we can leverage the
ASP.NET AJAX infastructure to make the managing of an AJAX application even sleeker. Now, let's imagine that we
want to elaborate the JSON response returned from the web service before sending it back to the client.
This can prove useful for many a reason, for example, to enrich the returned object with properties generated by
complex elaborations, which we would rather do on the server than on the client.
categorizing atmospheric turbulence, to the weather observation data returned from the Geonames web service we
have come to know in my previous articles. I want to point out that this is merely an example of a complex elaboration
that would generally take place on the server rather than on the client, but it could be substituted with any kind of data
transformation or elaboration that you would need to apply to the data before sending it back to the client.
Now, in order to do this, we might modify the returned JSON object directly as a string, but you can imagine how
cumbersome and errorprone this process would become if the elaborations to be made were less than trivial. We
need some more flexibility. And here's where the ASP.NET AJAX infrastructure comes to help us again.
What we want to do first, is convert the JSON response to a .NET object, in order to pave the way for the elaborations
that we are going to make. We can do this in a straightforward way, leveraging the .NET JavaScriptSerializer
class, which can be found in the System.Web.Script.Serialization namespace. But before starting the actual
deserialization process, we need to make some preparation. First of all, we need to create the class we want our
JSON object to be shaped into:
As you can see, the properties that we added to the class map directly to those present in the returned JSON object.
(See here if you haven't read my previous post and you want to see how the returned JSON string looks like). Also
notice that this is the place where we define the additional properties that we want to send to the client along with the
original ones; in this case, we added the stabilityClass property.
NOTE: You might notice that we used Automatic Properties, a new language feature introduced with C# 3.0,
to make our code more compact and readable (let alone saving a lot of keystrokes ;) ). You can read more
on Automatic Properties on Scott Guthrie's blog. If you are not using C# 3.0 yet, the only thing you need to
do in order to make this work, is to write basic properties or public fields rather than Automatic Properties.
Actually, if you look at the returned JSON string closely, you'll find out that the weather observation is not returned as
a toplevel object, but is itself the content of the toplevel weatherObservation property. This might seem redundant at
first, but this schema is due to fact that more than one weather observation can be returned from the Web Service if
desired, and in that case the weatherObservations property would contain an array of observations. Anyway, we can
overlook this detail for the moment; all we need to do now to make everything work smoothly, is define a new class,
containing a weatherObservation property:
Now we're ready to modify our GetWeatherByLocation method.
We'll add a call to the Deserialize<T>() method of the JavaScriptSerializer class. This method will return an
object of type T, containing the deserialized data, which we will use for all our subsequent computations. In particular,
Classes. Later, we'll use this value to set the stabilityClass property of our object. Let's see how the code looks
like:
As you can see, the last thing we do is serialize our object back to a JSON string before handing it back to the caller
(which happens to be our proxy Web Service). This is perfectly legitimate, but is an unnecessary step that can be
avoided, now that we are working with .NET objects. In fact, the AJAX framework can take the burden of serializing
and deserializing .NET objects to and from JSON onto its shoulders, in order to make the process of calling ASP.NET
Scriptenabled Web Services completely transparent to the user. Let's see how to do this.
return our .NET object rather than its JSONserialized counterpart; we'll have to change its signature, and return our
observation object without serializing it:
Then we'll have to propagate this change to the caller method, i.e. the Web Service's GetWeatherByLocation()
method:
namespace Mashup
{
/* To allow this Web Service to be called from script using ASP.NET AJAX,
* we need to set the following attribute. */
[ScriptService]
[WebService(Namespace = "Mashup")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WeatherService : WebService
{
[WebMethod]
public SingleWeatherObservation GetWeatherByLocation(double lat, double lng)
{
return GeonamesWeather.GetWeatherByLocation(lat, lng);
}
}
}
You can see that the Web Method returns a SingleWeatherObservation object rather than a string containing
its JSON representation. Now, we'll have to make some little changes to the client code in order to reflect the changes
made to the server side.
function callService()
{
var latitude = $get('txtLat').value;
var longitude = $get('txtLng').value;
Mashup.WeatherService.GetWeatherByLocation(latitude, longitude,
GetWeather_success, onFailed);
}
function GetWeather_success(e)
{
//var result = Sys.Serialization.JavaScriptSerializer.deserialize(e, true);
var result = e;
var weatherData = new Sys.StringBuilder();
var line;
for(var property in result.weatherObservation)
{
line = String.format("<b>{0}:</b> {1}<br/>",
property, result.weatherObservation[property]);
weatherData.append(line);
}
$get('divResult').innerHTML = weatherData.toString();
}
Nothing has changed from what we have seen previously, except for the first line in GetWeather_success(e); we
don't need to explicitly deserialize the argument received from the Web Service call anymore, as this is done under
the hood for us by the AJAX framework. We can assume that e is a Javascript object that closely mimics the structure
of the .NET object returned from the Web Method.
Notice that by default, JavaScriptSerializer supports most usual data types. However, you can serialize
and deserialize types that are not natively supported by JavaScriptSerializer by implementing custom
converters using the JavaScriptConverter class, and then register the converters by using the
RegisterConverters method. For more information, consult this page of the ASP.NET AJAX
Documentation, or have a look at this interesting article by Chris Pietschmann
As you can see, we have attained a completely transparent communication between server and client code. All the
details of serialization / deserialization to and from JSON are hidden from our view by the ASP.NET AJAX framework.