AJAX applications written for the ASP.NET platform work by sending HTTP requests to a server-side back-end. Aside from pages using the partial rendering engine - a sort of interceptor that uses XMLHttpRequest to place classic postbacks - an ASP.NET AJAX page requests data to a remote endpoint available over the HTTP protocol. Callable endpoints are public addresses for back end services. How would you write such services for an ASP.NET AJAX application?
The key thing that is going on here is that these services are not publicly available services, but just application services living inside the same application that calls them. More precisely, nothing really prevents developers and architects from designing services that any clients that understand the protocol can consume. However, any service should be considered primarily as part of the host application. So, how would you write an application HTTP service in ASP.NET?
The first, and fairly obvious, option that springs up to mind is using ASP.NET Web Services; that is ASMX endpoints. An AJAX application requires a different configuration than a classic ASP.NET application; this means that requests for an ASMX resource are filtered out and redirected to a special AJAX component if they contain a special header - the clear evidence that the request has been spawned by an AJAX page. The reason why the same software technology - ASP.NET Web services - is used for creating both WS-* Web services and AJAX local services in ASP.NET is that for a time it was just the only available option.
Starting with Visual Studio 2008 (code-named Orcas), now close to its RC status, you can use Windows Communication Foundation (WCF) to build AJAX-callable services. Overall, the developer's experience is mostly the same whether you use ASP.NET Web services or WCF services. However, the richness of the WCF platform - specifically designed to generate and support software services - is a no-brainer. A good question would be: why wait for Visual Studio 2008 to start using WCF services in ASP.NET AJAX pages?
Before the availability of the .NET Framework 3.5 "Orcas", the WCF platform had no built-in support for taking JSON as input and returning it as output. So what is it that the .NET Framework 3.5 really does with respect to WCF? It basically empowers WCF to support JSON serialization. Now WCF services can optionally output JSON, and not always SOAP envelopes, over HTTP. All that you have to do is configure an endpoint to use the
webHttpBinding binding model and enable web scripting through a new attribute. More detail on this in a moment.
Building a (Very) Simple Service
Having always been a huge fan of the bottom-up approach to things, I just can't learn anything without first testing it in a very simple scenario that then evolves as quickly as possible into a more realistic one. So let's simply create a new Web site in Visual Studio 2008 and click to add a new AjaxWcfService item and name it TimeService.
After confirming the operation, you find your project extended with a service endpoint (say,
timeservice.svc) and its related code-behind file placed in the App_Code folder; say,
timeservice.cs. In addition, the
web.config file is also modified to provide registration and discovery information for the service being created.
The TimeService class implicitly represents the contract of the service and its explicit implementation. The
OperationContract attributes play the same role you may know from any previous exposure to WCF programming. For the sake of simplicity, no interface is used to define the contract.
In the end, the TimeService class exposes a couple of public endpoints - named
The endpoint to reach the methods on this interface are defined in a SVC file, like the timeservice.svc file shown below.
The service host indicates the language being used to implement the service and the location of the source files. Finally, through the
Service attribute it indicates the name of the contract being used.
The final step before you can test the service is registering its usage in the
web.config file of the host ASP.NET application. Here's what you need to have:
First off, you register the list of behaviors for endpoints. In doing so, you define a behavior for your service - named
TimeServiceAspNetAjaxBehavior - and state that it accepts requests from the Web via script. The
enableWebScript element is logically equivalent to the
ScriptService attribute you use to decorate a Web service class for the same purpose.
Next, you list the services hosted by the current ASP.NET application. This preceding
web.config file has just one service named
TimeService with one endpoint using the TimeService contract and the
webHttpBinding binding model.
Testing the Service
The service is pretty much all set. How would you use it from the
<script> section of a client ASP.NET page? The steps required by a developer aren't much different from those required to invoke a Web Service. You start by registering the service with the script manager using the SVC endpoint.
When processing the markup, the
The proxy class is named after the namespace of the service, as declared by the
Namespace parameter of the
ServiceContract attribute. If you leave the parameter to its default value (
Tempuri.org), then the proxy class is named
Tempuri.org.TimeService. Let's assume the following, instead:
Figure 1 shows the sample page in action.
Figure 1: A page using a WCF service for time information.
That's enough for a quick introduction to WCF services and AJAX from the perspective of a developer who knows enough about ASP.NET AJAX. You're now in the condition to dig out a few of the intricacies specific of WCF. Let's talk, for instance, about the ASP.NET compatibility mode.
ASP.NET Compatibility Modes
When you create a new WCF service for ASP.NET AJAX, the service class is also decorated by default by the
AspNetCompatibilityRequirements attribute, which deserves a few words of its own.
While designed to be transport independent, when employed in the context of an ASP.NET AJAX application, WCF services may actually work in a manner that is very similarly to ASMX services. By using the
AspNetCompatibilityRequirements attribute, you state your will of having WCF and ASMX services to work according to the same model. One practical repercussion of this setting is that when a WCF service is activated, the runtime checks declared endpoints and ensures that all of them use the Web HTTP binding model.
The compatibility with ASMX services makes it possible for WCF services to access, for example, the
HttpContext object and subsequently other ASP.NET intrinsic objects. The compatibility is required at two levels. First, in the
web.config file where you use the following:
Second, developers need to explicitly choose the compatibility mode for a given WCF service by using the service
WCF services also support a zero-configuration mode where you don't need to enter anything in the
web.config file in order to publish endpoints. All that you do is summarized in the following schema for the SVC file:
Unfortunately, in Beta 2 of the .NET Framework 3.5 this option just doesn't work as expected. If used, it takes you to an error message about the fact that the binding only supports specification of exactly one authentication scheme in IIS. There's nothing wrong in your IIS configuration. It's only a "classic" bug in Beta 2 that will be fixed in RTM.
AJAX applications require services for building the back end of the system. In ASP.NET, there are just two software technologies to build services - ASMX Web services and WCF services, with the latter being a superclass of the former. AJAX communication, though, should use JSON data strings to move data back and forth. Adjusting the ASP.NET runtime for making ASMX Web services support JSON was a relatively easy task fully accomplished in the ASP.NET AJAX Extensions 1.0 and then in ASP.NET 3.5. Doing the same for the far richer runtime of WCF services took a bit more. That's why only in ASP.NET 3.5 you can build your AJAX back end of services using WCF. In future columns, I'll dig out more and more about the integration between WCF and AJAX.