Home / AJAX

Using JSON Syntax with Ajax

RSS
Modified on 2009/12/21 20:24 by Erik Reitan Categorized as Uncategorized
JavaScript Object Notation, or JSON, is a lightweight syntax for representing data. JSON is a subset of the JavaScript language and consists of JavaScript key-value pairs. It is text-based and uses Unicode. JSON nests data elements in a way similar to XML. Each instance of a JSON document describes one object with nested objects, arrays, strings, numbers, Boolean values, or null values. JSON is ideal for data interchange with Web services.

Note:

JSON syntax is defined at the http://www.json.org Web site.

There are several ways to use JSON as an interchange format for data. To call a service from an ASP.NET Web page, you add a ServiceReference element to the ScriptManager control. This automatically generates a JavaScript proxy class. When you use the JavaScript proxy class to call the service, JSON is used as the serialization format for the data that is exchanged between the browser and the server. For more information about using the ServiceReference element, see Ajax and Web Services and Using Web Services in Ajax.

Web pages that are not ASP.NET .aspx files cannot use a ScriptManager control. This topic describes how you can retrieve data in JSON format by creating a JavaScript proxy class.

Returning Data in JSON Format from an ASP.NET Web Service over HTTP

To enable an ASP.NET Web service to return data in JSON format over HTTP, you can mark the Web service class with the ScriptService attribute, which is in the System.Web.Script.Services namespace.

Note:

The ScriptService attribute was introduced in ASP.NET version 3.5.

The following example shows how to add the ScriptService attribute to a Web service Service class to enable the service to return data in JSON format.
using System;
using System.Web.Services;
using System.Web.Script.Services;
[WebService(Namespace = "http://tempuri.org/")]
[ScriptService]
public class Service : System.Web.Services.WebService
{
    [WebMethod]
    public string HelloWorld() 
    {
        return "Hello World";
    }    
}

You can call the service method directly by using the invoke method of Sys.Net.WebServiceProxy, as in the following example:
Sys.Net.WebServiceProxy.invoke("myservice.asmx", 
    "HelloWorld", true, null, succeededCallback, failedCallback);

The service returns data in JSON format. When the request returns, the JSON-formatted data is evaluated and passed as a JavaScript object or array to the function that is specified in the succeededCallback parameter.

Adding the ScriptService attribute also enables the ASP.NET Web service to automatically create a JavaScript proxy class. By referencing the Web service and appending "/js" to the script reference, you cause ASP.NET to generate the proxy class automatically. For example, if an ASP.NET Web service is in a file named Service.asmx, you would create the following script reference in markup:
<script type="text/javascript" src="service.asmx/js"></script>

You can also save the generated JavaScript proxy class by entering the Web service file name into the browser with the "/js" extension, and then saving the proxy file when you are prompted. This lets you use the JavaScript proxy class to call the service by calling the method directly on the proxy object. Again, JSON-formatted data is returned, and then evaluated and passed as an object or array to the succeeded callback function.

Returning Data in JSON Format from a Windows Communication Foundation (WCF) Service

The architecture of WCF separates how a message is serialized from its underlying transport. This means that data from WCF can be serialized by using a wide variety of formats, including text or binary. The text serialization capabilities include a number of formats, including SOAP, POX, and JSON.

Note:

If you use Microsoft Visual Studio 2008 (or later) and the .NET Framework 3.5 (or later), you can add an AJAX-enabled WCF Service to an existing project. In that case, you do not need to perform the tasks that are outlined in this section. The service is already configured to serialize data in JSON format.

To return data from a WCF service in JSON format, you add an attribute in the service code and set two attributes in the Web.config file for the service.

First, you add the WebInvoke attribute to the service, as in the following example:
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

[ServiceContract(Namespace = " ")] public interface Service { [WebInvoke(Method="POST",ResponseFormat=WebMessageFormat.Json)] [OperationContract] string HelloWorld(); }

public class ServiceImpl : Service { public string HelloWorld() { return "Hello World"; } }

Second, in the Web.config file, you specify the binding method as webHttpBinding in a service element. You then set the behavior by using the enableWebScript element. The following example shows a Web.config file for a service that sends JSON data over HTTP.
<system.serviceModel>
  <services>
    <service name="ServiceImpl">
      <endpoint 
          address=""
          binding="webHttpBinding" 
          contract="Service" 
          behaviorConfiguration="WCFServiceAspNetAjaxBehavior"/>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior 
          name="WCFServiceAspNetAjaxBehavior">
          <enableWebScript />
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
The enableWebScript behavior serializes a WCF message by using JSON encoding. The webHttpBinding binding option indicates that the endpoint is accessible through a Web programming model by using HTTP verbs such as GET and POST. WCF version 3.5 includes the webHttpBinding binding option to provide better interoperability with the ASP.NET AJAX library. It provides support for the "d" JSON encoding, as explained later in this topic.

As with an ASP.NET Web service, you can call the service operation from JavaScript, either by calling Sys.Net.WebServiceProxy.invoke or by using a JavaScript proxy object for the service. As with ASP.NET Web services, you can get the JavaScript proxy class by appending "/js" to the query string in the request. The following example shows how to reference a WCF service named WCF-JSON-Service.svc in markup:
<script src="WCF-JSON-Service.svc/js" 
    type="text/javascript" 
    language="javascript">
</script>


The WCF-generated JavaScript proxy class is identical to the one generated from an ASP.NET Web service except for the path information. WCF uses set_path to point to the Service.svc file instead of to the Service.asmx file.

Understanding the 'd' Parameter in ASP.NET AJAX JSON Data

If you create a custom implementation that returns data in JSON format, you should be aware of a potential security exploit that is referred to as array object constructor hijacking. The ASP.NET AJAX library uses a wrapper around JSON-formatted data to prevent this security exploit.

An array object constructor hijacking exploit makes it possible for a page to be compromised with a cross-site scripting attack. By sending a scripted request to a JSON service, it is possible to retrieve data from another domain that is running under the client's session. This potentially provides access to other sites that the client is logged into at the time. Because the response to the request is in JSON, it is parsed as a JavaScript statement.

For example, if the response is a set of bank account balances: "$1234.56", "$4567.34", "$6543.76", the malicious script could gain access to this data because it is a valid JavaScript statement. If a script is injected into the Contoso.com site that requests data from Woodgrovebank.com and sends it to evil.adatum.com, anyone who is logged into Woodgrovebank.com and then went to Contoso.com would expose session-sensitive data from Woodgrovebank.com to evil.adatum.com.

The ASP.NET AJAX library uses the "d" parameter for formatting JSON data. This forces the data in the example to appear in the following form, which is not a valid JavaScript statement:
{ "d" : ["$1234.56", "$4567.34", "$6543.76"] }
Because this is not a valid JavaScript statement, it cannot be parsed and instantiated as a new object in JavaScript. This therefore prevents the cross-site scripting attack from accessing data from AJAX JSON services on other domains.

The "d" parameter formatting is transparent to you when you use the enableWebScript configuration setting along with the webHttpBinding and WebInvoke attributes that are discussed earlier in this topic. The "d" parameter formatting is not used (and therefore data is vulnerable to cross-scripting security exploits) when you set the configuration file behavior to webHttp. You might do this to control the behavior of the service by writing code to send a POST request and parse the result.