An Extensive Examination of Web Services: Part 11
By Scott Mitchell
An Extensive Examination of Web Services Index
An Extensive Examination of Web Services is a multi-part article series spanning
several months. Listed below are the current "parts," along with a very brief synopsis and the
date published.
Part 1 - Examines the basics of Web services, what Web services are,
and the technologies and standards that serve as the underpinnings of Web services. (October 8th, 2003)
Part 2 - Examines creating Web services using Visual Studio
.NET. Looks underneath the hood of the code created by VS.NET. (October 15th, 2003)
Part 3 - Examines creating a client application that consumes
a Web service. Discusses the purpose and structure of a WSDL document, along with creating and using proxy
classes to consume a Web service. (November 5th, 2003)
Part 4 - Examines the utility of Web services and common
scenarios where Web services make sense. A business-oriented look at Web services. (November 19th, 2003)
Part 5 - Takes an in-depth look at XML serialization, which is the
process of converting a data type, such as an integer, array, or custom class, into its XML representation, and back again.
Every time a message is passed to or from a Web service, XML serialization transpires. (December 17th, 2003)
Part 6 - Looks at sending metadata to a Web method through the use of SOAP headers.
Examines defining and accepting a SOAP header on the Web service end, and looks at sending a populated SOAP header
from the client. (December 31st, 2003)
Part 7 - Examines how the incoming and outgoing messages to a Web
service can be programmatically modified via SOAP Extensions. (January 21st, 2004)
Part 8 - Learn about the Web Service Enhancements (WSE) and Microsoft's
free class library for implementing the WSE standards. (June 30th, 2004)
Part 9 - See how to implement UsernameToken authentication using
the WSE 2.0 Toolkit. (July 14, 2004)
Part 10 - Learn how to send large amounts of data as attachments using
DIME and WS-Attachments. (September 8th, 2004)
Introduction
As the previous ten installments in this article series have shown, the .NET Framework makes creating and consuming Web
Services a walk in the park. Creating a Web Service is as easy as marking a class with the WebService
attribute; Web Services can be easily consumed because the .NET Framework includes tools to build proxy classes given
a Web Service's WSDL file. All of the examples we have seen in previous installments in this article series have consumed
Web Services from server-side code. That is, a Web Service is consumed when a postback occurs and server-side code
in an ASP.NET page creates an instance of the proxy class and invokes one of its methods.
In 2007 Microsoft released their free ASP.NET AJAX framework, which simplifies
building AJAX-enabled ASP.NET applications (see An Introduction
to AJAX and Atlas with ASP.NET 2.0 for more information). The ASP.NET AJAX framework is best known for its
myriad of AJAX-enabled Web controls, but it also includes functionality to create and consume Web Services through
client-side script. Best of all, the workflow for creating script-accessible Web Services is very similar to creating
Web Services consumed through server-side .NET code. To mark a Web Service as being consumable from client script,
simply add the ScriptService attribute; the service can be consumed through script via an auto-generated
JavaScript proxy class.
In this article we'll look at how to use Microsoft's ASP.NET AJAX framework to consume Web Services from script.
We will also examine how the low-level communication differs between Web Services consumed from .NET code versus
Web Services consumed from JavaScript. Read on to learn more!
Getting Started with Microsoft's ASP.NET AJAX Framework
The first step for creating script-accessible Web Services is to ensure that you have Microsoft's ASP.NET AJAX framework
at your disposal. The AJAX framework does not support ASP.NET
version 1.x; if you are using ASP.NET version 2.0 you'll need to
download and install the free framework from http://www.asp.net/ajax/. (Refer to
the Get Started with ASP.NET AJAX video for more information.)
Future versions of ASP.NET will ship with the AJAX Framework, so there will be no need to download and install it separately.
Once you've installed the ASP.NET AJAX framework, launch Visual Studio. From the File menu choose to create a New Project.
The New Project dialog box will include an option to create an ASP.NET AJAX-Enabled Web Application. Choosing this option
will create a new Web Application Project that references the AJAX Framework assembly (System.Web.Extensions).
The System.Web.Extensions assembly includes essential AJAX-related Web controls and the classes necessary to
create script-accessible Web Services. Additionally, this project types creates a default Web.config file
with much additional markup. The markup that is germane to this article is the following:
These two bolded lines remove the default HTTP Handler for Web Service files (.asmx) and replace it with
the ScriptHandlerFactory from the ASP.NET AJAX framework. This handler determines whether or not the request
is coming from client-side script. If it is not, it dispatches the request to the default .NET Web Service handler.
If the request is coming from client-side script, however, it deserializes the incoming parameters, invokes the method,
serializes the response, and sends it back to the client.
An alternate HTTP Handler is needed for Web Service requests eminating from client-side script because a different
message format protocol is used. Recall that .NET Web Services, by default, serialize the response and request payloads
into SOAP envelopes. When the requests are coming from a client-side script call, however, the messages are serialized
using JavaScript Object Notation (JSON). JSON is a text-based, lightweight data
exchange format that is often used in AJAX-enabled web applications for a host of reasons. A thorough description
of JSON is beyond the scope of this article; for more information, read An
Introduction to JavaScript Object Notation (JSON) in JavaScript and .NET.
Creating a Script-Accessible Web Service
Creating a script-accessible Web Service is just like creating a regular, server-side accessible Web Service. Start
by adding a Web Service to your Web Application Project. This will create a class with the WebService attribute.
As we've seen from earlier installments, you can add methods to the Web Service by creating public methods marked with
the WebMethod attribute. At this point we have a Web Service that can be called from .NET code. To make it
accessible from client-side script, simply add the ScriptService attribute to the class (just like the
WebService attribute).
At the end of this article you'll find a downloadable demo application that includes a Web Service named
~/Services/Calculator.asmx. This Web Service is accessible from both .NET code and from client-script. It
offers four methods: Add, Subtract, Multiply, and Divide. Each
method takes as input two integer parameters and returns the sum, difference, product, or quotient. The following
code shows the class and the Add and Divide methods; the Subtract and Multiply
methods have been removed for brevity.
using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel; using System.Web.Script.Services;
namespace ScriptServices.Services
{ [ScriptService]
[WebService(Namespace = "http://example.com/Calculator")]
public class Calculator : System.Web.Services.WebService
{ [WebMethod]
public int Add(int x, int y)
{
return x + y;
}
... Subtract and Multiply methods removed for brevity ...
[WebMethod]
public int Divide(int x, int y)
{
if (y == 0)
throw new DivideByZeroException("Parameter y cannot be equal to 0.");
return x / y;
}
}
}
Note the addition of the ScriptService attribute. The attribute class is in the System.Web.Script.Services
namespace, which is why I have using System.Web.Script.Services;. Each accessible method is marked with the
WebMethod attribute.
That's all there it to creating the script-accessible Web Service! It's just like creating a regular Web Service. The only
difference is the inclusion of the ScriptService attribute.
Consuming the Web Service from Client-Side Script
To consume a script-accessible Web Service from client-side script, you'll need to start by adding a ScriptManager control
to the page. The ScriptManager control
is part of the ASP.NET AJAX framework that enables developers to perform AJAX-related operations, including invoking
script-accessible Web Services.
From the ScriptManager control, we need to indicate that we want to be able to invoke the Calculator.asmx
Web Service. This is accomplished by adding a ServiceReference element to the control's Services
section:
This, in essence, builds a JavaScript proxy class for accessing the Web Service from client-side script. Using the proxy
class from JavaScript is a cinch. To demonstrate this, the download at the end of the article includes a web page that
has two textboxes to collect numbers and four buttons labelled Add, Subtract, Multiply, and Divide. There's also a
textbox at the bottom of the page that displays the sum, difference, product, or quotient.
Clicking any of these buttons runs a particular JavaScript method that grabs the numbers entered into the textboxes and
calls the Web Service. Here's the abbreviated code from the client-side Add_OnClick function, which runs
when the Add button is clicked:
function Add_OnClick()
{
// Get the values from the textboxes
var xValue = document.getElementById("X").value;
var yValue = document.getElementById("Y").value;
// Call the Web Service! ScriptServices.Services.Calculator.Add(xValue, yValue, CalculationSuccessCallback);
}
To call the Web Service, simply reference the appropriate Web Service method like so: Namespace.WebServiceName.Method(parameters, SuccessCallbackMethod, FailureCallbackMethod).
For this example, the Web Service's namespace is ScriptServices.Services (to verify this, check the namespace
value in the code listing in the "Creating a Script-Accessible Web Service" section); the Web Service name is Calculator
and the method to call is Add. Two values are passed in as the parameters to Add (xValue
and yValue). Web Service calls through script are asynchronous, meaning that control returns to the
browser immediately after the above bolded line is executed. When the Web Service returns, the
CalculationSuccessCallback function (which we need to create) is invoked:
function CalculationSuccessCallback(serviceResult)
{
var ResultsTextBox = document.getElementById("Results");
ResultsTextBox.value = serviceResult;
}
serviceResults contains the actual value returned by the Web Service method (for Add, it's the
sum of the two input parameters). This return value is then displayed in the results textbox at the bottom of the page.
Handling Web Service Invocation Errors
If the Web Service call completes as expected, the specified function (CalculationSuccessCallback, in this
case) is invoked. But what happens if something goes awry? Perhaps the web server that the Web Service runs on is down.
Or maybe the executed Web Service method threw an exception. The Divide method, for example, will bomb out
if the user tries to divide by zero. How is such a situation handled in the client script?
If we do not modify our code at all, a failed Web Service invocation fails silently. The CalculationSuccessCallback
function is never called. No script error is raised. It's as if the Web Service call was never made.
If you want to handle script errors, you need to instruct the proxy class to call a different method in the face of
an error. This can be accomplished by specifying the failure callback method much like we did with the successful callback method:
var ResultsTextBox = document.getElementById("Results");
ResultsTextBox.value = "THERE WAS AN ERROR";
}
The above function starts by displaying the exception message in a messagebox. It then displays the text, "THERE WAS AN ERROR"
in the results textbox.
Conclusion
Traditionally, Web Services were called from compiled programs like from Windows Applications and the code-behind classes
of ASP.NET web pages. But as web applications are continually pushing more functionality down to the client in the name
of UI responsiveness, developers are needing to invoke Web Services directly from the client, without the cost of a roundtrip
back to the server. Microsoft's ASP.NET AJAX framework makes it easy to create script-accessible Web Services, and also offers
integrated tools for invoking said Web Services directly through JavaScript. Rather than use SOAP, these Web Services use
JSON, a popular message protocol for AJAX-enabled web applications.