Accessing Server-Side Data from Client Script: Accessing JSON Data From an ASP.NET Page Using jQueryBy Scott Mitchell
When building a web application, we must decide how and when the browser will communicate with the web server. The ASP.NET WebForms model greatly simplifies web development by providing a straightforward mechanism for exchanging data between the browser and the server. With WebForms, each ASP.NET page's rendered output includes a
<form>element that performs a postback to the same page whenever a Button control within the form is clicked, or whenever the user modifies a control whose
AutoPostBackproperty is set to True. On postback, the server sends the entire contents of the web page back to the browser, which then displays this new content. With WebForms we don't need to spend much time or effort thinking about how or when the browser will communicate with the server or how that returned information will be processed by the browser. It just works.
While this approach certainly works and has its advantages, it's not without its drawbacks. The primary concern with postback forms is that they require a large amount of information to be exchanged between the browser and the server. Specifically, the browser sends back all of its form fields (including hidden ones, like view state, which may be quite large) and then the server sends back the entire contents of the web page. Granted, there are scenarios where this large quantity of data needs to be exchanged, but in many cases we can use techniques that exchange much less information. However, these techniques necessitate spending more time and effort thinking about how and when to have the browser communicate with the server and intelligently deciding on what information needs to be exchanged.
An Example: A Simple Master/Child Report Web Page
Consider a simple master/detail report web page like the one shown below, which uses a drop-down to list the categories of products for sale. Selecting a category from the drop-down displays information about those products that belong to the selected category.
Traditionally, this master/detail report web page would be implemented using a DropDownList control for the list of categories and a ListView control (or GridView) for
the list of products, with the DropDownList control's
AutoPostBack property set to True. By setting the
AutoPostBack property to True, the
to re-request the web page, sending along all of the form fields (including the just-selected category). On postback we would repopulate the products ListView with those
products that belong to the selected category and send back the entire page's HTML, which the browser would then display.
While this approach certainly works and is quick and easy to implement, it has the disadvantage of being very "chatty." Every time there's a new category selected the form is submitted, resulting in a new HTTP request to the server, which sends all of the form fields (including view state). Moreover, the server doesn't just return the "new" markup (namely, those products for the selected category), but needlessly returns all of the page's markup, including the DropDownList markup and other content on the page that has not changed.
The demo available for download at the end of this article includes a page named
TraditionalApproach.aspx that implements the above master/details report
page using the techniques we just discussed. Let's examine how much information in exchanged between the client and the server with this approach. First off, whenever
the user chooses a new category the browser submits the form, which results in a payload of 2,398 bytes. In a perfect world, we'd need to only send a fraction of this information
to the server. After all, we only need to report the newly selected category, right? Now what about the data that gets sent back from the server? The response from the
web server for this demo clocks in at 10,424 bytes. However, the actual markup that is specific to the list of products in the selected category comes in at less than
4,500 bytes, meaning that more than half of the data sent from the server down to the browser was markup that did not change, things like the layout markup, the markup
for the categories drop-down, and so on.
- Building a server-side service that returns or modifies data when invoked. In the master/detail report example, we'd need a service that returns the list of categories (for the drop-down list) as well as details about the products in a specific category.
Exchanging Information Between the Browser and Server
How the browser sends its data to the server usually depends on whether the browser is asking to retrieve data or if it is modifying data. Each HTTP request specifies
a method, which indicates the type of action to be performed. The HTTP protocol supports a variety of methods, the two most common being
GET request indicates that the browser wishes to retrieve a resource and that no other action should be performed, whereas a
POST request is used when submitting data to be processed. (An ASP.NET WebForm is referred to as a postback form because when submitted, the browser
makes a POST request back to the same web page, sending the form field names and values as the payload of the
POST request.) So, when retrieving data
from the server the browser should use a
GET request and when modifying data a
POST request should be used.
The only way a browser can send information to the server through a
GET request is via the URL (such as in the querystring) or as an HTTP Header. Therefore,
when using script to retrieve data from the server any information that needs to be supplied in order to retrieve that data should be specified in the querystring.
(For this article, I want to focus on the data retrieval scenario; we'll look at data modification examples in a future installment.)
Creating a Server-Side Service For Returning Data
In order to implement the master/detail report example, we need a service that returns the
Descriptionfields of all of the categories in the database as well as the
Discontinuedfields of those products that belong to a specified category. Such a service should be accessible over HTTP by requesting a URL like
http://www.yoursite.com/Services/GetProductsInCategory.aspx?CategoryID=1and should return the requested data as JSON.
There are a variety of ways in which such a service could be constructed. This article examines using an ASP.NET page as the service.
(Future installments will explore additional options.) Let's start by using an ASP.NET page. The demo available for download includes a folder named
inside which you'll find a page named
NorthwindService.aspx. This is an ASP.NET page that contains no declarative markup (I removed all content from the
.aspx page except for the
@Page directive). My idea here was to have this service be invokable in the general format
NorthwindService.aspx/ACTION/ID, where ACTION is a required string indicating the type of request to perform and ID is
optional, depending on the ACTION. Specifically, the service is built to handle the following cases:
NorthwindService.aspx/GetCategories- returns the
Descriptionvalues of all of the categories in the database, and
- NorthwindService.aspx/GetProductsByCategory/CategoryID - returns the
Discontinuedfields of those products whose
CategoryIDfield equals the value specified by CategoryID.
Page_Loadevent handler. First, the page's
Content-Typeis set to
application/json, which is the MIME type for JSON data.
Request.PathInfo value is split into its individual parts.
Request.PathInfo is a little known property that returns the path information
for a resource with a URL extension. A URL extension is that part that comes after the name of the web page, namely the
/GetProductsByCategory/CategoryID. Here we split on the forward slash character to see if the user wants to retrieve categories or products.
(Note: Error checking code has been removed for brevity.)
In the above code I have a string variable named
output, which is what is sent back to the browser at the end of the
Page_Load event handler
Response.Write). Depending on whether the user requested to retrieve all categories or the products in a specific category, the
data will be retrieved, serialized into JSON, and stored in the
To understand how this works, let's see the code that executes when the user specifies a
Note that in the above code I use a LINQ query to retrieve the
Description fields form all of the
categories in the database. Next, this collection of data is converted into JSON by calling the
ToJson method. This method does not exist in the .NET Framework;
rather, it's an extension method I have created in another class in the project (
This extension method uses the .NET Framework's
class to serialize a .NET object (in this case, a collection of category objects) into JSON. The code to serialize data into JSON using the
class is quite simple:
Testing the Service
With this code in place, you can test the service by visiting it directly through a browser. For instance, visiting
NorthwindService.aspx/GetCategoriesreturns the following (formatted and abbreviated) JSON:
In JSON, the square brackets denote an array while the curly braces denote an object. Therefore, the above JSON represents an array of objects, where each object has
Description. To see the JSON returned by the
NorthwindService.aspx/GetProductsByCategory/1, which returns those products that belong to the Beverages category.
NorthwindService.aspx Service from Client-Side Script
The demo application includes an ASP.NET page named
UsingAnASPNETPage.aspx that shows how to call the ASP.NET server-side service. This web page's markup
includes a drop-down list with just one item (-- Select a Category --) and a
<div> element where the selected category's products will be displayed.
categories drop-down list and
<div> are populated by client-side script that calls the server-side service.
When the page loads we start by invoking the service's
GetCategories action. To make an HTTP GET request to a URL that returns JSON data, use jQuery's
getJSON function, which takes two input parameters: the URL to request and the function to execute
once the data is returned. When the data is returned we want to enumerate the results and for each category add a new
<option> element to the
The above code invokes the
NorthwindService.aspx/GetCategories service. When the data is returned, jQuery's
function is used to iterate over the results. For each category returned, a new
<option> element is created, its inner text is set to the value of
CategoryName property; its
value attribute is set to the
CategoryID. Following that, the
is appended to the
categories drop-down list.
Recall that the service returns an array of category objects (as JSON). When the call to the service completes and this information is returned to the browser, the
function defined as the second parameter in
getJSON is executed. Here,
data is the array of categories. The
each function steps
through each category. Here,
elem is the instance of the category object we are currently iterating through. Note that we can access the properties of this
After the above code executes, the drop-down lists the categories in the database. We also need to call the service whenever the user selects a new category.
To accomplish this, we create a client-side event handler for the drop-down's
change event. First off, we need to determine the selected
which can be accessed via
$("#categories").val(). If the selected
CategoryID equals -1 then that means the user chose the "-- Select a Category --"
option, so we want to hide the
<div>; otherwise, we need to call the service, passing in the selected
This is done using the
getJSON function. When the server returns its data, we need to iterate through the data and build up the HTML to display in the
As we saw before, the
getJSON function takes two input parameters - the URL of the service and a function that is executed when the server responds with
its JSON payload (namely, an array of product objects). In the function that executes when the server responds, we start by checking to see if the array of products
returned from the server contains no products. In that case, we display, "There are no products in this category..." Otherwise, we loop through the set of products
each function, as before) and build up a string of HTML to display. At the conclusion of the loop, we display the HTML in the
<div> using jQuery's
Evaluating Our Progress
With this code in place, let's walk through what happens when a user visits our page.
- The user points their browser to
UsingAnASPNETPage.aspx. The server responds with the markup for this page.
NorthwindService.aspx/GetCategories). The server responds with a JSON payload listing the categories in the database. Upon receipt, the browser enumerates the categories and adds an
<option>element to the drop-down list for each returned category.
- If the user selects a category from the drop-down, the browser makes a request for the service
NorthwindService.aspx/GetProductsByCategory/CategoryID. The server responds with a JSON payload listing the products in the specified category. Upon receipt, the browser enumerates the products and builds up an HTML string displaying the pertinent information. This string is then displayed within the
This article explored one way to build a server-side service and one way to access the data from script; namely, we focused on using an ASP.NET page to serve data and jQuery to retrieve it. Moreover, we only examined how to retrieve data from the server. In future installments we'll explore alternative techniques for implementing server-side services and for accessing them from the client, and we'll see how to use these techniques to perform inserts, updates, and deletes, as well.
Until then, Happy Programming!