ASP.NET 3.5 introduces a new attribute called “ScriptService” in the System.Web.Script.Services namespace. A ScriptService makes it easy to call a web service decorated with the WebService attribute from JavaScript. Applying the ScriptService attribute to a WebService causes it to accept JSON (JavaScript Object Notation) data for the input parameters and to return JSON data. This completely eliminates the need to parse XML as you must when using standard SOAP (Simple Object Access Protocol) web services, or the need to create ASPX pages to hijack and parse/format the output.
Creating the ScriptService
The sample script service shown below is designed to accept a request to the RetrieveRecords
WebMethod The service creates the specified number of random records and returns a List of SampleRecord classes.
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class ScriptServiceExample : System.Web.Services.WebService
{
[WebMethod]
public List RetrieveRecords(int records)
{
List recList = new List();
Random rnd = new Random();
for (int i = 1; i <= records; i++)
{
//Create a sample record
SampleRecord r = new SampleRecord()
{
Id = i,
DateTime = DateTime.Now.ToString(),
RandomName = GenerateRandomName(rnd),
RandomNumber = rnd.Next()
};
//Add it to the list we plan to return.
recList.Add(r);
}
return recList;
}
private string GenerateRandomName(Random rnd)
{
int len = rnd.Next(25);
string s = "";
for (int i = 0; i < len; i++)
{
s = s + Convert.ToChar(rnd.Next(32, 127));
}
return s;
}
}
public class SampleRecord
{
public int Id { get; set; }
public string RandomName { get; set; }
public int RandomNumber { get; set; }
public string DateTime { get; set; }
}
The preceding service example functions as both a standard SOAP WebService and as a ScriptService (accepting and returning JSON). Adding the attribute [System.Web.Script.Services.ScriptService]
is the only change necessary to give the WebService the ability to work with JSON data transparently. To communicate with the ScriptService using JSON, you need to note these restrictions:
- The ScriptService will respond only to JSON data sent via a
POST
method. - Incoming JSON data must match the parameters of the WebMethod.
- The
POST
must have a Content Type ofapplication/json; charset=utf-8
. - The data returned will be formatted as a JSON object; however the actual result of the method call will be stored in an object named
d
.
Using the Prototype Framework
With the restrictions in mind, you can use the Prototype JavaScript framework to call the ScriptService as follows:
new Ajax.Request("/ws/ScriptServiceExample.asmx/RetrieveRecords",
{
method: 'post',
contentType: "application/json; charset=utf-8",
postBody: Object.toJSON({ 'records': ddl.value }),
onSuccess: function(res)
{
var t;
t = "<table border='1'> <tr> <td> <strong>Id</strong></td> <td>" +
"<strong>Name</strong></td> <td> <strong>Number</strong>" +
"</td> <td> <strong>Date Time</strong></td> </tr> ";
res.responseJSON.d.each(function(r)
{
t = t + " <tr> <td> " + r.Id + "</td> <td> " +
r.RandomName + "</td> <td> " + r.RandomNumber +
"</td> <td> " + r.DateTime + "</td> </tr> ";
});
t = t + " </table> ";
tbl.update(t);
}
});
The Prototype framework provides the Ajax.Request
method which you call to connect to the ScriptService. Populate the method
and contentType
parameters as described in the restrictions listed at the end of the preceding section. Populate the postBody
parameter with the JSON data you want to send to the service. Conveniently, Prototype provides an Object.toJSON
method to serialize an object to JSON. When the call completes, Prototype calls the onSuccess
function, which creates a simple table, loops through the returned array, and populates the table. Note that the code accesses the JSON data returned from the ScriptService using the res.
responseJSON.d
object passed as the parameter to the onSuccess
function.
Using the jQuery Framework
You can easily perform the same operation in jQuery using similar JavaScript, as shown below:
$.ajax({
url: "/ws/ScriptServiceExample.asmx/RetrieveRecords",
type: "POST",
contentType: "application/json; charset=utf-8",
data: $.toJSON({ 'records': ddl[0].value }),
dataType: "json",
success: function(data) {
var t;
t = "<table border="1"> <tr> <td> <strong>Id</strong></td>" +
"<td> <strong>Name</strong></td> <td> " +
"<strong>Number</strong></td> <td> " +
"<strong>Date Time</strong></td> </tr> ";
jQuery.each(data.d, function(rec) {
t = t + " <tr> <td> " + this.Id + "</td> <td> " +
this.RandomName + "</td> <td> " + this.RandomNumber +
"</td> <td> " + this.DateTime + "</td> </tr> ";
});
t = t + " </table> ";
tbl.html(t);
}
});
You use the jQuery $.ajax
method to set the parameters, parameter type, and contentType
as above. In this case, set the dataType
parameter to json
. Setting the data parameter is not as easy as Prototype because jQuery does not natively provide a convenient method to convert an object to JSON. However, a small (2K) jQuery add-on provides a simple $.toJSON
method. You can download the jQuery-JSON add-on through Google Code. To access the JSON data returned from the ScriptService use the data.d
object in the parameter passed into the success function.
As you can see, ScriptServices provides an excellent new addition to ASP.NET, giving it transparent JSON communication abilities, and drastically reducing the amount of code necessary to communicate using JSON. Even though this article shows only examples of using Prototype or jQuery for communications, you should note that many of the other frameworks are capable of working with ScriptServices as well. Also, remember that giving your WebServices the ability to act as ScriptServices involves adding only a single line of code.
About the Author
Chris Bennett is a manager with Crowe Horwath LLP in the Indianapolis office.