Inside ASP.NET AJAX back end services

This article was originally published in VSJ, which is now part of Developer Fusion.
In my spare time at conferences and training sessions, I often get asked questions regarding AJAX. Most of the time, these are about the role of partial rendering, tricks to optimize it, and the architectural points it misses out. The remark that sparked off this article regards the ASP.NET AJAX implementation of services.

In recent months, I have witnessed a common misconception about services in ASP.NET AJAX. These services – many think – are not pure REST services, and worse yet they use SOAP under the hood. That ASP.NET script services are not pure REST is an acceptable and largely correct statement. Microsoft itself recognizes this implicitly by telling us that it’s working on REST data services in project Astoria (more on this later). On the other hand, the idea that ASP.NET script services use SOAP internally is simply incorrect.

How to build services in ASP.NET?

A script service is a remote piece of code that resides on the Web server in the same domain – often, in the same application – as the caller page. The service is reachable via HTTP and is backed by a runtime environment that knows how to serialize and deserialize data to and from the Web client. How would you build such a service in ASP.NET? More importantly, how would you do it without heavily restructuring the runtime of ASP.NET? You don’t need to look far, there’s just one option in the .NET Framework 2.0 and two options if you move up to consider the newly released .NET Framework 3.5.

The first option entails using an ASP.NET Web service to implement the remote service. In this case, the URL for client scripts to connect is an ASMX endpoint. Behind this endpoint, you have a live instance of a class that derives from WebService.

The second option is only supported in ASP.NET 3.5 and requires that you expose any needed interface through a Windows Communication Foundation (WCF) service. This service will be hosted in IIS and reached via HTTP. In this case, the endpoint is a SVC resource that binds to an instance of a managed class with the contracted interface.

The first aspect to dig out here is the use of the term ASP.NET Web service. We’re not talking about WS-* Web services hosted on a Web server and communicating through HTTP POST packets padded with SOAP envelopes. What developers are called out to create are in effect just classes nearly identical to classic SOAP-powered Web services:

using System.Web.Services;
[ScriptService]
public class TimeService : WebService
{
	[WebMethod]
	public DateTime GetTime()
	{
		return DateTime.Now;
	}
}
The devil is in the detail, though. Have you noticed the [ScriptService] attribute that boldly decorates the class definition? That’s the key that radically changes the runtime behavior of the resulting class even when that class is deployed behind an ASMX endpoint.

Another fundamental element to consider is the following fragment excerpted from the web.config file of an ASP.NET AJAX application:

<httpHandlers>
	<remove verb=”*” path=”*.asmx” />
	<add verb=”*” path=”*.asmx”
		validate=”false”
	type=”System.Web.Script.Services.
		ScriptHandlerFactory…” />
</httpHandlers>
The first node underneath the <httpHandlers> section removes any HTTP handlers that are installed for ASMX resources, including the standard handler that ASP.NET installs to serve ASMX requests for SOAP-powered Web services. The second node adds a new handler for ASMX requests defined by the ASP.NET AJAX framework. This short excerpt demonstrates that in spite of the appearances ASMX requests are handled differently in ASP.NET AJAX.

So, how exactly? Each ASMX request is forwarded to a registered HTTP handler factory – the ScriptHandlerFactory class. An HTTP handler factory is used in ASP.NET when dynamic conditions determine the actual HTTP handler to be used for a particular request. In this case, a request for an ASMX resource can potentially be served in either of two ways: via a script service or a classic Web service. The handler factory assesses request information and loads up the proper HTTP handler. Figure 1 shows the complete flow diagram for ASMX requests in ASP.NET AJAX applications.

Figure 1
Figure 1: Flow diagram for ASMX requests in ASP.NET AJAX applications

As its first step, the ScriptHandlerFactory class checks whether the incoming request has a given content type. The following snippet shows some pseudo-code that illustrates what really happens in the ASP.NET AJAX runtime. Note that a HTTP handler factory class implements the IHttpHandlerFactory interface which counts on two methods – GetHandler and ReleaseHandler. The code below gives an idea of the implementation of the GetHandler method in the script handler factory of ASP.NET AJAX. Note that this code has been slightly adapted for clarity, but is closely related to real ASP.NET AJAX code. Class names, in particular, are real:

public IHttpHandler GetHandler(
	HttpContext context,
	string requestType,
	string url,
	string pathTranslated)
{
	IHttpHandlerFactory factory;
	if (RestHandlerFactory.
		IsRestRequest(context))
	{
		factory = new
			RestHandlerFactory();
	}
	else
	{
		factory = new
			WebServiceHandlerFactory();
	}
	:
}
The WebServiceHandlerFactory class is defined in the System.Web.Services.Protocols namespace and has been part of the ASP.NET platform since the beginning. The RestHandlerFactory class is new in ASP.NET AJAX. For some reason the REST term is conventionally used to indicate a request that needs to be treated differently from a classic Web service request, although it has a similar endpoint. I feel the use of the term REST here is ambiguous, to say the least. On the other hand, these classes are not public and not meant to be public. So in theory, they could have christened, say, the RestHandlerFactory class with any arbitrary name. But they opted for a name with REST in it. To fix things up, let’s say that in this context REST just merely indicates a non-SOAP solution.

The key step in the GetHandler method of the ScriptFactoryHandler class is the check made through the IsRestRequest method. The method accepts the HTTP context of the request and returns a Boolean value. At the highest of abstraction, the goal of the method is determining whether the current request is coming from a script. More concretely, the method simply checks the content type of the request. Here’s some illustrative code:

internal static bool
	IsRestRequest(HttpContext context)
{
	HttpRequest request =
		context.Request;
	return String.Equals(
		request.ContentType,
		“application/json”,
		StringComparison.
		OrdinalIgnoreCase);
}
Any ASMX request that doesn’t have a content type of application/json is automatically served by the classic ASP.NET Web service handler. In other words, any ASMX request with a non application/json content type is implicitly assumed to carry SOAP envelopes in the body. Will the condition “content type set to application/json” equals “request comes from script” always be valid? Of course, there’s no guarantee that all requests with that content type come uniquely from the script of an AJAX Web page. It’s too easy to use the classes in the System.Net namespace, and arrange a Windows Forms application that calls into the back end of an AJAX application. However, any ASMX requests that come from an ASP.NET AJAX Web page aimed at a back end service is guaranteed to have the proper content type set. This is hard-coded in the Microsoft AJAX Client Library that all ASP.NET AJAX pages use to place remote calls.

Once the handler in charge of serving the request has been identified, it takes up the responsibility of verifying whether the invoked service can be invoked from script. So the RestHandlerFactory instantiates the real HTTP handler, and has this check whether the service class is decorated with the ScriptService attribute. If no such attribute can be found, an exception is thrown – see Figure 2.

Figure 2
Figure 2: Script code from ASP.NET AJAX pages can’t call any type of Web service

Script Services are local to the application

The bottom line is that services used to implement the back end of an ASP.NET AJAX system are specific and local to the application. They are implemented as ASP.NET Web services only because that was the only service-based API available when ASP.NET AJAX was planned. In ASP.NET 3.5, in fact, you can drop entirely the ASP.NET Web service model and fully embrace the WCF programming model. The reason why this requires version 3.5 of the .NET Framework and is not supported on, say, version 3.0 is that WCF version 3.0 didn’t include ad hoc support for JSON.

A script service receives input data and sends return values back using a JSON stream. So the service infrastructure must be able to deserialize JSON strings to platform-specific objects and, vice versa, it must be powerful enough to serialize objects to JSON strings.

AJAX script services decorated with the ScriptService attribute are still callable from any code in the universe that has access to the ASMX endpoint and that knows how to handle SOAP. Take a look at Figure 3.

Figure 3
Figure 3: Double access to an ASMX endpoint

Any script service is potentially dual and can be accessed either via JSON or SOAP. Why is it so? Because in ASP.NET AJAX, a script service is implemented via the ASP.NET Web service interface and automatically gets to support a variety of calling protocols. The same happens for WCF services. However, both Web and WCF services offer a number of configuration options through which you decide bindings and behaviors. If you simply want your ASP.NET Web service, exposed as a script service, to be accessible only by JSON callers, then all that you have to do is adding the following markup to the web.config file of the hosting application:

<webServices>
	<protocols>
		<clear />
	</protocols>
</webServices>
If you’re even a little bit familiar with the ASP.NET configuration schema, you should grasp the sense of the markup. ASMX Web services do not support any protocols implemented through the standard ASP.NET handler: no HTTP POST, HTTP GET, SOAP over HTTP POST, not even the Documentation protocol used locally to test Web services. Given the preceding settings, the service can only be accessed outside the standard ASP.NET Web service handler – that is, only via JSON and from ASP.NET AJAX pages.

Operating script services

Created as ASP.NET Web services, AJAX script services are invoked from within JavaScript proxy classes. A proxy class for a given service is automatically generated and linked to the page whenever a service is referenced with the page’s script manager, as below:
<asp:ScriptManager runat=”server”
	id=”ScriptManager1”>
	<asp:ScriptReference
		path=”service.asmx” />
</asp:ScriptManager>
Calls sent through the proxy use the HTTP verb specified in the definition of the service class. By default, the HTTP POST verb is used to transport parameters and return values as JSON strings. However, by adding an optional [ScriptMethod] attribute to individual methods in the service you can force the use of the HTTP GET verb and XML serialization. The arguments you can use with the [ScriptMethod] attribute are described in Table 1.

Table 1 – Parameters for the [ScriptMethod] attribute
Parameter Description
ResponseFormat Specifies whether the response will be serialized as JSON or as XML. JSON is the default format.
UseHttpGet Indicates whether a HTTP GET verb can be used to invoke the Web service method. HTTP POST is used by default. Note that opting for HTTP GET raises some serious security concerns. It makes it virtually possible for an attacker to call the method’s URL via an injected <script> tag thus automatically uploading any sensitive local cookies to the source of the <script> tag – the attacker’s Web site.
XmlSerializeString Indicates whether all return types, including strings, are to be serialized as XML. The default is false.

Unless the default configuration is changed, the ASP.NET AJAX transportation mechanism uses HTTP POST throughout to carry JSON strings. To what extent, is this approach REST-ful?

REST in brief

REST as an architectural pattern is formalized here. REST is not an architecture per se. It is rather a set of design principles that some concrete architectures may meet better than others. According to Wikipedia, the fundamental facts about REST can be summarized as:
  • Application state and functionality are divided into resources
  • Every resource is uniquely addressable using a universal syntax
  • All resources share a uniform interface for the transfer of state to and from the client
If that sounds a bit too abstract or if you, like me, sometimes need something more concrete to make sense of it, let me expand and rephrase the fundamental REST facts as:
  • Applications are built around resources
  • Applications access resources using a protocol that is client/server, stateless and cacheable (for example, HTTP)
  • Resources are described using common formats
  • Resources are addressed using URIs
  • Resources are manipulated using a limited and general purpose interface, for example the set of HTTP verbs: GET, POST, PUT, DELETE
So a typical true REST service will use HTTP verbs to work on its resources and expose those resources via URIs. Recognized examples of true REST implementations are Google’s GData service and the Ruby On Rails programming model.

Going deeper into the concepts and practices of REST is beyond the boundaries of this article. For more information on REST-ful services, I recommend you take a look at RESTful Web Services, by Leonard Richardson and Sam Ruby (O’Reilly, 2007).

Being an architectural pattern for designing services, REST is associated with AJAX simply because AJAX applications need a service-based back end. The question is, is there currently any REST in ASP.NET AJAX services? Frankly, not much. But it mostly depends on how tolerant you are regarding the absolute quantity of REST principles required to label a system as RESTful. If you just need a minimum quantity of REST principles to call a system RESTful, you can then include in the list any systems that don’t use SOAP and Web services. What many of these systems often do, though, is tunneling remote function calls over HTTP returning plain XML, or perhaps JSON, data streams. This is more or less what ASP.NET AJAX does. It uses HTTP to carry function calls using JSON data streams instead of SOAP. On the server, though, you find objects in what is really close to a RPC model. And RPC is the complete opposite of REST.

An RPC application is exposed as a web of related objects, each with its own contracted interface. The client must have intimate knowledge of the object identity in order to communicate with it. A RESTful Web application takes a different approach and aims at creating a relatively small set of common resources that clients can address using a uniform syntax. Furthermore, each resource addressed provides links to further resources so that at each stage the client knows where it could go without knowledge of the whole resource set.

In summary, the only REST that can be reasonably found in ASP.NET AJAX (despite the naming of some internal classes) is the use of HTTP (but limited to the POST verb) and JSON to execute calls.

Code-name Astoria

Astoria is the codename of a new Microsoft technology first unveiled at MIX07 and later incorporated in ASP.NET Futures. It is a library that facilitates the creation of services that are reachable over HTTP and expose their data through URIs. More importantly, any interaction with the service happens in terms of HTTP verbs invoked over resources and carrying JSON or XML data. Does it sound like Microsoft’s transposition of REST principles? Yes, it does.

The Astoria plaform is still young, fast evolving and far from the Beta stage. If you pay a visit to the Astoria site, though, you can learn more about its objectives and details. Astoria will probably not make its debut until the next major upgrade of ASP.NET, currently slated for late 2008 at the earliest. For architects and developers involved with the design of AJAX-oriented systems, script-callable WCF services are probably the best way to go today. Today you consume back end services using JavaScript proxies. This top-level aspect isn’t likely to change with Astoria, so switching to a new service model may be easier and, more importantly, affect only a portion of your system.


Dino Esposito is an instructor for Solid Quality Mentors, and a trainer and consultant based in Rome. He is the author of various books, including Windows Shell Programming, Instant DHTML Scriptlets and Windows Script Host Programmer’s Reference. He is also a regular speaker at Bearpark’s DevWeek conference, and will be presenting a number of sessions at DevWeek 2008 in March 2008.


Why “Script Services”?

So ASP.NET AJAX allows you to implement the back end engine of the application using script callable services. To avoid confusion, I’ll refer to these services as “script services”. Much of the ASP.NET AJAX literature uses terms like Web services, REST services, data services, or just services. If you google for “script services” you aren’t going to get results relevant to the idea of AJAX pages and AJAX architectural patterns. So why am I insisting on coining a new term to indicate a special type of service? It’s because the services you use to build the back end of an ASP.NET AJAX system are special, and none of the alternative names listed above perfectly describes their structure and usage. They’re not entirely Web services; at least not in the sense of WS-* Web services. Services in ASP.NET AJAX are not entirely REST services, because they always use HTTP POST verbs to send messages. They’re not SOA services because, for example, they’re not autonomous services; and autonomy is one of the all-important four SOA tenets. The bottom line is that the back end of ASP.NET AJAX applications is made of services that manipulate some data in both input and output. These services feature just one key attribute – they must be callable from JavaScript code. That’s why, all considered, I like to call them script services.

You might also like...

Comments

About the author

Dino Esposito United Kingdom

Dino Esposito is an instructor for Solid Quality Mentors, and a trainer and consultant based in Rome. He is the author of various books, including Windows Shell Programming, Instant DHTML Script...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Linux is only free if your time has no value” - Jamie Zawinski