Json In Asp.net Ajax_client Script

  • April 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Json In Asp.net Ajax_client Script as PDF for free.

More details

  • Words: 3,950
  • Pages: 15
client script >> 

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 AJAX­related, 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 human­readable, easily­parsable data­interchange 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 built­in 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: var json = '{"firstName":"Marco", "lastName":"Anastasi", "age":27}'; var person = eval('(' + json + ')'); 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 built­in 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 server­side 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 RPC­style generated for us by the framework. But the question is: how? When faced with the necessity to create a server­side 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, * we need to set the following attribute. */ [ScriptService] [WebService(Namespace = "Mashup")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WeatherService : WebService { [WebMethod] public string GetWeatherByLocation(double lat, double lng) { return GeonamesWeather.GetWeatherByLocation(lat, lng); } } } 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 { public class GeonamesWeather

{ private readonly static string FindNearbyWeatherUrl = "http://ws.geonames.org/findNearByWeatherJSON?lat={0}&lng={1}";

public static string GetWeatherByLocation(double lat, double lng) { string formattedUri = String.Format(CultureInfo.InvariantCulture, FindNearbyWeatherUrl, lat, lng);

HttpWebRequest webRequest = GetWebRequest(formattedUri); HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); string jsonResponse = string.Empty; using (StreamReader sr = new StreamReader(response.GetResponseStream())) { jsonResponse = sr.ReadToEnd(); } return jsonResponse; }

private static HttpWebRequest GetWebRequest(string formattedUri) { // Create the request’s URI. Uri serviceUri = new Uri(formattedUri, UriKind.Absolute);

// Return the HttpWebRequest. return (HttpWebRequest)System.Net.WebRequest.Create(serviceUri); } } } As you can see, what the  GetWeatherByLocation()  method does is simply act as a proxy. We call the remote web  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", "observation":"LICC 231720Z 29009KT 9999 FEW035 SCT070 16/07 Q1009", "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>

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.
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() { var latitude = $get('txtLat').value; var longitude = $get('txtLng').value; 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, element), it resolves to element.getElementById(id).

After that, we're finally ready to call our proxy service. We do that by calling the Javascript proxy method generated for  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 JSON­serialized 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 result = eval('(' + e + ')'); var weatherData = new Sys.StringBuilder(); var line; for(var property in result.weatherObservation) { line = String.format("{0}: {1}
", property, result.weatherObservation[property]); weatherData.append(line); } $get('divResult').innerHTML = weatherData.toString(); } function onFailed() { $get('divResult').innerHTML = 'Something went terribly wrong!'; }  

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 server­side 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   built­in  JavaScriptSerializer.  If   you   simply   substitute   the   first   line   in  GetWeather_success() with the following line: var result = Sys.Serialization.JavaScriptSerializer.deserialize(e, true); 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. In fact, what we will see today, is how to add a  Stability Class  property, computed used the Pasquill method for  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 error­prone 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:  

public

class

WeatherObservation

{ public public public public public

string string string int int

public

string

public

int

public

string

clouds

{

get;

observation

{

weatherCondition {

windSpeed ICAO elevation

get; {

windDirection {

set;

get; get; get;

set;

} }

set; set; set;

} } }

{

get;

set;

}

{

get;

set;

}

countryCode

{

get;

set;

}

public

double

lat

{

get;

set;

}

public

double

lng

{

get;

set;

}

public public

int int

temperature dewPoint

{ {

get; get;

set; set;

} }

public public public public public

int string string int

humidity

{

get;

stationName

{

datetime

get;

{

get;

hectoPascAltimeter

string

stabilityClass

set;

{ {

}

set;

}

set;

get; get;

}

set;

}

set;

}

}   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 top­level object, but is itself the content of the top­level 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:  

public

class

SingleWeatherObservation

{ public

WeatherObservation

weatherObservation

}   Now we're ready to modify our GetWeatherByLocation method.

{

get;

set;

}

We'll add a call to the Deserialize() 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,  we'll pass this object to our  ComputeStabilityClasses()  method, in order to compute the suggested Stability  Classes. Later, we'll use this value to set the stabilityClass property of our object. Let's see how the code looks  like:  

public

static

string

GetWeatherByLocation(double

lat,

double

lng)

{ string formattedUri = String.Format(CultureInfo.InvariantCulture, FindNearbyWeatherUrl,

HttpWebRequest HttpWebResponse

webRequest response

string using

=

=

sr

=

new

lng);

GetWebRequest(formattedUri);

(HttpWebResponse)webRequest.GetResponse();

jsonResponse

(StreamReader

lat,

=

string.Empty;

StreamReader(response.GetResponseStream())) {

jsonResponse

=

sr.ReadToEnd();

}

JavaScriptSerializer

ser

=

new

JavaScriptSerializer();

SingleWeatherObservation observation = ser.Deserialize<SingleWeatherObservation>(jsonResponse); observation.weatherObservation.stabilityClass = ComputeStabilityClasses(observation.weatherObservation); return

ser.Serialize(observation);

} private static string ComputeStabilityClasses(WeatherObservation weatherObservation) { // }  

...

code

for

computing

the

Stability

Class

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  Script­enabled Web Services completely transparent to the user. Let's see how to do this. First of all, we need to make some little changes to our  GetWeatherByLocation()  method in order to make it  return our .NET object rather than its JSON­serialized counterpart; we'll have to change its signature, and return our 

observation object without serializing it:  

public static SingleWeatherObservation GetWeatherByLocation(double lat, double lng) { //....

Same

code

as

return

above

observation;

}   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

=

[WebServiceBinding(ConformsTo public

class

=

WeatherService

"Mashup")] WsiProfiles.BasicProfile1_1)] :

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, GetWeather_success,

longitude, onFailed);

} function

GetWeather_success(e)

{ //var

result

=

Sys.Serialization.JavaScriptSerializer.deserialize(e,

var var

result weatherData

= =

for(var

e;

new

var

true);

Sys.StringBuilder(); line;

property

in

result.weatherObservation)

{ line

=

String.format("{0}: property,

{1}
",

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.

Related Documents

Json
December 2019 6
Aspnet
June 2020 25
Json
November 2019 4
Security In Aspnet
May 2020 13
Aspnet-statemgmt
October 2019 34