In .NET 3.5, Microsoft has introduced a number of features that make it easier to create WCF services that are directly accessible over HTTP using REST (Representational State Transfer) principles that rely on pure HTTP semantics.

In the 3.0 version of .NET WCF and also ASP.NET, Web services already included the ability to publish HTTP-based SOAP services (with basicHttpBinding). This includes the ability to retrieve data from these service calls via straight HTTP Urls and returning results with XML formatting. However, this functionality is fairly limited and was never really designed as an end all solution to making WCF and Web service endpoints accessible directly to generic HTTP clients. The new REST features in .NET 3.5’s WCF implementation make direct non-SOAP HTTP access a full class citizen.

The Rise of REST

REST service access is becoming quite popular with many large public community and social sites publishing REST-based APIs that allow retrieving and supplying data to these Web applications. For example, consider the photo site Flickr, which has an extensive API that allows you to retrieve images in various formats with querying for image tags, authors, and filenames as well as support for uploading new images to the service. Amazon has for years published their product catalog through an API that is available both via SOAP and REST with the REST API being more popular these days. Social neworking site Facebook also created a REST-based API that can be used to interact with the service so status updates can be handled from other applications.

It’s ironic that REST-rather than SOAP-based Web services-is turning out to be the preferred Web API that companies use to share data between public applications and REST is now making the Web at your FingerTips slogan much more of a reality than it was in all the years of the attempt for Web services to achieve the same goal. Many companies realize that public sites that have a sharable API for clients to access and provide content can greatly increase the value of the service to customers/visitors and enhance the Web experience. Certainly for large sites like Flickr, the API is a big driving force for the service’s popularity.

The problem with Web services has always been complexity. SOAP-based Web services technology has gotten insanely complex with standards upon standards piled on top of the original SOAP spec with compatibility suffering as a result. Many old SOAP clients don’t support Web services built on newer technologies (for example, try using the SOAP Toolkit against a WCF service) making for anything but a truly interoperable solution. On top of that, SOAP is pretty much off limits to browsers with no client-side SOAP support.

Contrast Web services with the simplicity of REST services which are accessible from any browser or other HTTP client. Often times you can test a REST service from the browser address line and you can use any simple HTTP client to retrieve REST-based content. REST is certainly not a replacement for Web services as it doesn’t provide the breadth of features like security, quality of service, transactions, queueing etc. But for public-facing open APIs that rely on sharing information, REST simply is easier to access from anywhere and easier to work with. Additionally, REST’s basic interface and focus on public and sharable access force a lot more thought on building APIs that are not just functional but also as easy as possible to access to make it easy for clients to consume the service interface.

WCF, .NET 3.5 and REST

To improve the ability to publish data to HTTP and URL-based endpoints, WCF in .NET 3.5 includes a new webHttpBinding that allows publishing service methods using standard REST HTTP semantics. In effect, this new binding provides an official way to publish a service endpoint via plain, non-SOAP HTTP access that is accessible directly via a URL and GET data on the URL or with POST data.

At first you may think, “Ho hum we already have the ability to call a service with HTTP GET or POST operations with Web services and, to some extent, with WCF (using basicHttpBinding and special flags that enable direct URL activation).” However, .NET 3.5 adds a number of useful features:

  • Url Routing When you specify a method to be invoked via REST you can specify a UriTemplate that lets you create pretty URLs such as /myservice.svc/GetPerson/10. You can define the format of the template any way you like regardless of the method name. In IIS 7 you can even do away with having to reference the .svc file.
  • Parameter Mapping As part of the URL routing you can specify parameters with a special syntax ({CustPk} for example) with the parameters being automatically mapped to an input parameter from the URL. Unfortunately mapped parameters must be of type string only and aren’t auto-mapped to a non-string type.
  • XML and JSON Data Parameters can be passed and results returned either using JSON or XML. JSON (JavaScript Object Notation) is important for any data that you might want to consume in an AJAX-based client, which is becoming a more frequent scenario. JSON support is new in .NET 3.5, but even XML support can be had without the overhead of a SOAP packet.
  • Easier Configuration You can configure the new webHttpBinding without any Web.config settings. Rather, you can specify a host factory as part of the Service definition, which handles the most common configuration settings. Host factories exist for raw REST services or for Microsoft AJAX hosted services with WebServiceHostFactory or WebScriptServiceHostFactory, respectively.
  • DataContractJsonSerializer A new serializer that can serialize and deserialize JSON objects to and from .NET code that makes it easy to let your own code create JSON output with just a few lines of code. If the WCF REST services are not to your liking you can roll your own service or HttpHandler implementation that can take advantage of the JSON serialization features exposed by .NET 3.5 without actually requiring WCF.

Creating a REST-based JSON Service

The easiest way to create a WCF REST service is to create a new WCF service in an ASP.NET Web site or Web Application Project and use the Factory attribute to use the WebServiceHostFactory:

<%@ ServiceHost Language="C#"
    Debug="true"
    Service="TimeTrakkerService"
    CodeBehind="~/App_Code/TimeTrakker.cs"
    Factory="System.ServiceModel.
             Activation.
             WebServiceHostFactory"
%>

The factory attribute enables specification of a WCF service factory, which is responsible for loading and configuring a service host. The WebServiceHostFactory is a generic factory that sets up typical settings for REST-style services. Using the factory here lets you avoid having to explicitly configure the service in Web.config, which removes what is probably the most complex part of creating WCF-style services. If you plan on using the service as a front end for an ASP.NET AJAX client, use the WebScriptServiceHostFactory instead.

Instead of using the above factory you can also explicitly configure the service in Web.config, but be aware that there are a ton of options and decisions to be made when you go this route. Before I get into that, let me just show you a quick REST WCF implementation so you can get a feel for what the code requirements are.

Creating the WCF Service Interface and Implementation Class

With the WCF webHttpBinding you have to explicitly mark methods of a service interface that you want to publish as a REST endpoint. Typically, WCF endpoints are classes that implement a given service contract interface. This is still the case with webHttpBinding-you still have an Interface and a class that inherits from it-but in addition, each interface method that is published as a REST endpoint needs an explicit [WebInvoke] attribute that includes a few settings to describe how the endpoint is found and how it serves its data.

Listing 1 shows a couple of service methods that call into a business object that gets and saves a customer.

In this example I’m using a CustomerEntity object, which is a LINQ to SQL object generated by the LINQ to SQL engine. Specifically, this class is marked up with a [DataContract] attribute that marks the class as serializable to WCF. It’s important that any objects you pass in and return must be marked with [DataContract] or [Serializable].

You start with an interface that is marked with a [ServiceContract] attribute and add the [OperationContract] attributes to each of the methods to expose to the service in standard WCF fashion. The service implementation then inherits these settings.

What’s new for REST services is the [WebInvoke] attribute (there’s also a subset [WebGet] attribute), which is used to configure the REST behavior of specific methods. REST services are configured on the method level rather than at the service level, which is very un-WCF like. However, in the REST scenario this makes some sense as each method may have different requirements as to how it deals with incoming and outbound data. What’s nice is that you can still use the service implementation as an endpoint for non-REST services, which simply ignores the [WebInvoke] attribute.

Message Formats

You can specify what message format to use for the service. The choices are XML (the default) or JSON and in this case I choose JSON because I want to call the service via AJAX. You can also specify whether you want the data to be returned Bare (the default) or Wrapped. Bare holds just the raw object data-either a value or object represented as JSON or XML. Wrapped includes a root node that WCF objects inject into the messaging stream. If you’ve seen ASP.NET AJAX JSON messages you have already seen a wrapped format where inbound parameters are wrapped into an object with properties for each parameter name and result values are returned as an object with one result object property that contains the actual result value or object.

For JSON messaging, Bare formatting means you get a generic JSON object that is usable by just about any AJAX framework, although Microsoft ASP.NET AJAX will choke on this object as it’s expecting a proprietary JSON format, which requires some additional configuration settings that I’ll cover later. For now I’ll focus on Bare JSON requests.

UriTemplate: Url Formatting and Routing

The first method of the service also uses a UriTemplate, which defines the path in terms of the URL to access the service. UriTemplate is a new class in .NET 3.5 that provides Uri-based format strings and template text replacement on a Uri instance. WCF uses this class and the above template, GetCustomer/{CustomerPk}, indicates that I want a URL like this:

http://mysite.com/MyApp/
TimeTrakker.svc/GetCustomer/1

The curly brackets in the Uri template are mapped to any parameters by name in the method that is called. Here I’m using the PathInfo of the URL to specify the parameters which results in a somewhat cleaner looking URL than using query string parameters, for example. One limitation of the PathInfo routing is that parameters can only be mapped to strings so for the example above, CustomerPk value of 1 cannot be automatically mapped to an int.

If you’d like the parameter to parse automatically to its proper simple .NET type you can use query string parameters. So if you change the template to:

TimeTrakker.svc/GetCustomer?Pk={customerPk}

And change the method signature to:

CustomerEntity GetCustomer(int customerPk)

the Pk query string value is automatically converted into an int when the method is called. If you use query string parameters, however, it may not even be necessary to use UrlTemplates at all as query string mapping is natively supported without a UriTemplate. Simply match the query string key with the parameter name and WCF will do the rest.

Some of you may note that even the URLs with PathInfo routing still contain the .svc extension, which looks rather un-REST like. Unfortunately this is required by WCF in order to route the request to the service. If you want to strip the .svc extension you have to resort to URL rewriting in ASP.NET by checking for specific URL patterns and adding the .svc extension as needed. Jon Flanders shows a simple but not all that generic way to do this here. If you’re dealing with AJAX callback methods this probably won’t matter much, but if you’re building a public API it’s probably not a bad idea to set up UrlRewriting to provide friendlier URLs.

Generic AJAX Clients Calling the REST Service

To give you an idea of what calls from a generic AJAX client look like, let’s start with a service method defined like this:

[OperationContract]
[WebInvoke(Method = "GET",
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle=WebMessageBodyStyle.Bare)]
CustomerEntity GetCustomer(int customerPk);

You can call this service method from a raw client AJAX solution like this (using my wwHoverPanel library):

ajaxJson("TimeTrakkerService.svc/
          GetCustomer?customerPk=1",
         null,
         function (result)
           { alert(result.Company); },
             onError, {method: "GET"}
         );

This client function makes a GET call to a URL and expects a JSON result which is returned as a value/object to a callback handler (the third parameter). You can specify optional transport parameters in the final object map parameter, which here overrides the default POST behavior and uses GET instead.

The output from the server method call looks like this:

{"Pk":1,"UserId":"0","LastName":"Strahl",
 "FirstName":"Rick","Company":"West Wind",
 "Address":"32 Kaiea Place","City":"Paia",
 "State":"HI","Zip":"96779",
"Entered":"\/Date(1187812800000-1000)\/",
"Updated":"\/Date(1192241460000-1000)\/",
"tversion":[0,0,0,0,0,1,45,46]}

Because the data sent around is bare JSON it’s easy to use and consume by any generic AJAX client like in this case wwScriptLibrary, or a tool like jQuery or Prototype. You may notice, however, that dates are represented as strings with special formatting by WCF. JavaScript doesn’t include a date literal and so WCF-as well as any ASP.NET AJAX ScriptService-use a special string format that both the client- and server-side frameworks understand and can parse. wwScriptLibrary understands the format and parses it correctly, which is one of the reasons I use it for a generic sample above.

Here’s another example using jQuery to make the same call:

jQuery.getJSON(
  "TimeTrakkerService.svc/
  GetCustomer?customerPk=1", null,
  function(result) { alert(result.Company);
}
);

getJSON is nice for simple REST AJAX calls that return JSON, but if you need more control over the actual data sent to the server (as we’ll need to do POST calls with JSON payload) using the longhand AJAX function is a better choice:

jQuery.Ajax(
    
    {
      url: "TimeTrakkerService.svc/
            GetCustomer?customerPk=1",
      type: "GET",
      dataType: "json", // result data type
      success: function(result) {
      alert(result.Company); },
      error: function( xhr, message, ex)
    
             { alert("Ajax Error: " +
               message); }
    }
  );

Note though that native jQuery doesn’t convert the date values so you’d have to apply some special parsing and evaluating of the values. You can find out more about Microsoft date parsing here.

Passing Data

As you can see in the examples, you can apply an HTTP method verb to the method implementation but unfortunately you can only apply one verb at a time so it’s not possible to have a method that responds both to GET and POST operations. I haven’t found a way to map both GET and POST to the same Uri even by creating multiple methods that use different UriTemplates with the same method name. This seems to be a rather glaring omission-REST is all about easy access to remote APIs and being able to call a method either with POST or GET seems to make a lot of sense.

In light of this it may be a good idea to design your API with only POST or only GET interfaces to keep things consistent. If your service includes complex inbound parameters then POST is the likely option, otherwise go with the simpler GET interfaces. Ultimately GET interfaces are more usable and require no special explanation to consumers of the API as you can only pass simple parameters on the URL. With POST, the format of the POST data and how objects are passed becomes important and so it’s naturally more involved to consume data this way. Also keep in mind that GET requests can cache for performance while POST requests cannot.

GET method calls pass parameters via directly mapped query string keys where each key matches a parameter name. Alternately you can use UriTemplates to map parameters as described earlier. Keep in mind that query string parameters automatically do type conversion while PathInfo-based parameters require string input parameters on the service methods.

POST parameters are passed either as XML (the default) or JSON, which is configured in the WebInvoke attribute with the MessageBodyFormat option. If you plan on using these REST calls from an AJAX client the JSON route is the most likely candidate for passing parameters.

The default POST style is WebMessageBodyStyle.Bare, which is a single value or object, which effectively means that you can only pass a single parameter to the WCF method. In this mode simply pass a single JSON value to the server and that single value is mapped to a single input parameter of a method. This is the default behavior.

If your method has multiple input parameters you have to switch to WebMessageBodyStyle.WrappedRequest (or .Wrapped, which wraps both request and response) which wrap the parameters into an object like this:

 { name: "Rick", count: 3 }

This style is also what ASP.NET AJAX clients call a server with. The disadvantage of this style of calling is that you have to know and specify the exact parameter names and you have to pass JSON data to the server. Output generated in a wrapped format looks like this:

{"HelloWorldResult":"Rick Rick Rick "}

Another result with an object return value looks like this:

{"GetCustmerResult": {"Name": "Rick",
                      "Company": "West
                       Wind"} }

There’s a ‘root’ object that holds the single result. Generally for anything but ASP.NET AJAX, a wrapped method response has no value and should be avoided.

Message Formatting

You get a fair bit of control over the message using the WebInvoke POST options, but at the same time you are also limited in terms of supporting multiple types of clients. If you want to support both ASP.NET AJAX and raw AJAX clients like jQuery, or like me wwHoverPanel, there aren’t really any good solutions short of creating two completely separate service interfaces and mapping them onto the same implementation class.

For REST interfaces it may simply be best to pass single parameters to the server using JSON. The easiest way is to pass a single value to the server and WCF automatically handles the deserialization of the JSON (or XML) value into the matching type on the parameter signature. So if you have a method of type Customer that has Company and Name properties, you pass a raw JSON string in the POST buffer with a content type of application/json. The object passed should match the structure of the .NET object parameter. Internally .NET uses the new DataContractJsonSerializer to deserialize the object and it can deal with missing properties assigning only those matching property/field values that are found in the inbound JSON string. For example, on the Person object I can pass only the Company property, which leaves the Name property in the .NET object at its constructed default value.

Coming back to the earlier example, let’s switch the GetCustomer method to use POST. You can now pass a single JSON parameter to the server. If I have this definition:

[OperationContract]
[WebInvoke(Method = "POST",
 ResponseFormat = WebMessageFormat.Json,
 //UriTemplate = "GetCustomer",
 BodyStyle=WebMessageBodyStyle.Bare)]
CustomerEntity GetCustomer(int customerPk);

I can call it with wwScriptLibrary as follows:

ajaxJson("TimeTrakkerService.svc/
          GetCustomer", 1,
      function (result)
      { alert(result.Company); }, onError);

which produces identical results to the GET command shown earlier. Here the value 1 is passed and turned into a JSON string that is POSTed to the server. With jQuery the same call looks like this:

// Cheating - using wwScriptLibrary to
// create JSON since jQuery doesn't
// include native JSON encoding
var jsonData = JSON.serialize( 1 );
    
// jQuery Ajax function to call server
$.Ajax( {
  url: "TimeTrakkerService.svc/GetCustomer",
  type: "POST",
  contentType: "application/json",
  data: jsonData, // input data
  // don't parse input data as map
  processData: false,
  dataType: "json", // result data type
  success: function(result)
      {alert(result.Company); },
  error: function( xhr, message, ex)
      { alert("Ajax Error: " + message); }
} );

Note that jQuery doesn’t include native JSON encoding so you need to use some sort of JSON encoder. There’s a toJSON plug in or you can use Douglas Crockford’s JSON2 Converter.

One problem with JSON parsers/encoders is that JavaScript doesn’t have a standard for a Date Literal value and Microsoft uses a string with special formatting (ie. "\/Date(19139121-1000)\/"). WCF, the ASMX ScriptService as well as few of the .NET libraries available use this format. This solution, while it looks proprietary, is as good as any since there’s no standard on how to encode a date in JSON. In wwScriptLibrary I’ve created a modified version of Douglas Crockford’s original JSON parser that includes support for WCF and ASP.NET AJAX-style date formatting, which is one reason I prefer to use it over other choices for raw AJAX scenarios. You can grab the modified JSON code out of the wwHoverPanel library and use it with other AJAX clients if you like-the code is quite compact.

You can also pass more complex objects from the client. The SaveCustomer method takes a Customer object as input.

[OperationContract]
[WebInvoke(Method = "POST",
 ResponseFormat = WebMessageFormat.Json,
 BodyStyle = WebMessageBodyStyle.Bare)]
bool SaveCustomer(CustomerEntity
                  customerEntity);

Here’s the code to call the method using wwScriptLibrary:

function SaveCustomer()
{
    // Using existing Customer reference
    // loaded in GetCustomer()
    Customer.Company = "West Wind " +
        new Date().toLocaleTimeString();
    Customer.Updated = new Date();
    
    // Or create an object on the fly
    // if that makes sense
    // var Customer =
    // { Pk:1,Company:"West Wind",
    // Name:"Rick" };
    
    var svc=
      "TimeTrakkerService.svc/SaveCustomer";
  
    ajaxJson(svc,
             Customer,
             function (result)
             { alert(result); },
             onError
            );
}

The only difference here is that the parameter is an object. The ajaxJson function accepts a JavaScript value or object and turns it into JSON by default so all you have to do is pass in an object and it goes to the server as a JSON string.

Note that if the object only includes partial properties only those properties are sent to the server. The WCF method then instantiates the object and updates only the passed properties. This works well when you need to pass only a set of variable values/parameters but it doesn’t work in this scenario because there’s no way for the server to know what properties have been updated and which are supposed to be null or ‘empty’ on the Customer entity. So here the object is first loaded from the server (in GetCustomer()), updated and then sent back to the server in full.

This is one of the key things to understand about the WCF REST implementation: It relies on type mapping on input. All types that are passed in and out of WCF methods must be marked as [Serializable] and must be fully qualified types-you can’t pass around type Object or things like anonymous types in .NET 3.5 because WCF uses the type signature rather than an object instance to deserialize objects. WCF also cannot return types like a DataSet/DataTable/DataRow. Actually, you can but they are returned as an XML representation in a JSON object which contains a single property that holds the XML, which isn’t terribly useful.

WCF REST services are based on an RPC model and they work best if you can keep to this model. All communication that the server sees from the client is handled through the class interface. Unlike ASMX Web services, which were closely tied to ASP.NET, by default you also don’t get direct access to HttpContext.Current. The reasoning for this non-dependence on ASP.NET even in an ASP.NET application is that you can potentially host a REST service outside of IIS using self or WAS hosting, for example, which might be very useful for local applications where you want to duplicate an online AJAX environment.

So far I’ve talked about raw AJAX support using pure JavaScript clients. The reason I mentioned these clients first rather than the more popular ASP.NET AJAX is that support for raw AJAX clients simply wasn’t supported out of the box prior to .NET 3.5 due to ASP.NET AJAX’s use of a specialized JSON format (basically the “wrapped” format). Now with WCF REST support, bare AJAX messaging becomes a first class citizen in WCF.

ASP.NET AJAX Support

If you want to use ASP.NET AJAX with the WCF REST JSON services, things are actually a bit easier. ASP.NET AJAX services doesn’t require any special attributes because the transport mechanism always uses wrapped requests in the special JSON format that ASP.NET AJAX uses. The script service support also provides the client proxy class that maps the service methods to a client class through the /jsdebug switch in the same way ASMX ScriptService references work.

The ASP.NET ServiceHost implementation can also take advantage of a WebScriptServiceHostFactory to provide easy configuration without having to muck with Web.config settings. Simply use a service definition like this:

<%@ServiceHost
    Language="C#"
    Service="TimeTrakkerService"
    CodeBehind="~/App_Code/
                TimeTrakkerServiceMsAjax.cs"
    Factory="System.ServiceModel.
      Activation.WebScriptServiceHostFactory
%>

Then define your service interface and implementation class. When using ASP.NET AJAX you don’t need to use [WebInvoke] attributes because it always uses wrapped POST data to pass parameters to the server using its client proxy functionality. As a result, the ServiceContract interface is a little simpler:

using System;
using System.ServiceModel;
using TimeTrakker;
    
[ServiceContract(Namespace="WcfAjax",
                 Name="TimeTrakkerService")]
public interface ITimeTrakkerServiceMsAjax
{
    [OperationContract]
    string HelloWorld(string name,
                      int count);
    
    [OperationContract]
    CustomerEntity GetCustomer(
                      int customerPk);
    
    [OperationContract]
    bool SaveCustomer(CustomerEntity
                      customerEntity);
}

Note that you should specify a namespace and name for the service. Unlike ASMX services which use the code namespace and classname for the client class, WCF services use the service Namespace and Name attributes for the name of the client class. The client class exposed in the proxy thus becomes WcfAjax.TimeTrakkerService.

My first thought was that I could simply use my existing implementation class and implement both this new ITimeTrakkerServiceMsAjax interface and the ITimeTrakkerService interface on the class. Unfortunately WCF balked at having the same class implement two service interfaces. So as a workaround I created a TimeTrakkerServiceBase class with the actual implementations:

// Implementation code goes here
public class TimeTrakkerServiceBase {…}

and then created two inherited classes that provide the required service interfaces and have no actual code associated with them:

public class TimeTrakkerService :
TimeTrakkerServiceBase, ITimeTrakkerService
    
public class TimeTrakkerServiceMsAjax : TimeTrakkerServiceBase, ITimeTrakkerServiceMsAjax

and voilà-I now have a single implementation class that supports both Microsoft ASP.NET AJAX and raw JSON clients albeit with two different service URLs.

Now you’re ready to consume the service on the client. To use the service, add a ScriptManager to the ASP.NET page:

<asp:ScriptManager ID="ScriptManager"
   runat="server">
    <Services>
        <asp:ServiceReference Path=
         "~/TimeTrakkerServiceMsAjax.svc" />
    </Services>
</asp:ScriptManager>

And then call the server simply by calling the methods of the service from JavaScript:

function GetCustomer(callback)
{
    WcfAjax.TimeTrakkerService.GetCustomer(
    1,GetCustomer_Callback,onError);
}
function GetCustomer_Callback(result)
{
    alert(result.Company);
}

And that’s really all there’s to it. It’s easier than generic AJAX, because ASP.NET AJAX simply does things only one way, so there are no choices to make about which format to use. It uses its proprietary wrapped JSON formatting and provides the script proxy on the client and it just works. The nice thing about this approach is the fact that you don’t have to do ANYTHING special to your service implementation as long as the service follows the basic RPC guidelines.

Configuration

As is usually the case with WCF, the most difficult part of creating a service is to set up the configuration properly. As I mentioned earlier, using the WebServiceHostFactory or WebScriptServiceHost is the easiest way, but unfortunately to do so you lose some configurability in the process.

Even with WebServiceHostFactory there are a myriad of overlapping and somewhat confusing configuration options available. One thing that I ran into while experimenting with the different configuration options on the [WebInvoke] attribute is that many of the options are mutually exclusive in surprising ways. For example, you can configure the service to use ASP.NET AJAX-style messages, but when you do you can’t use a UriTemplate. This makes sense in that the Microsoft ASP.NET AJAX extensions pass all JSON data in POST buffers, but it’s frustrating that the service couldn’t just ignore UriTemplate when called from Microsoft ASP.NET AJAX or even exclusively when the flag is enabled in Web.config.

The reason this is troublesome is because the configuration for most behaviors aren’t made on the service as a whole but on individual methods, which means a simple change like switching from bare JSON to Microsoft ASP.NET AJAX-style messaging requires changing the WebInvoke attribute on every freaking method.

In short, you have to ensure that you define clearly up front what type of data you want to serve. There’s no easy switching back and forth as is typically the case with WCF services.

On the up side, once you’ve defined the service you can use the service for webHttpBinding access or any other service types like basicHttpBinding, wsHttpBinding or TcpBinding for example. So if you have existing services and need to publish these services alongside your REST implementation, the WCF REST implementation might be enticing.

Manual configuration of Web.config for a REST service requires a number of entries. It took me quite a bit of trial and error to even get the Web.config operation to work at all. Listing 2 shows a roughly equivalent configuration for the WebServiceHostFactory configuration using Web.config settings:

ASP.NET Compatibility

By default, WCF’s WebHttpBinding has ASP.NET support disabled. This means that you don’t get access to HttpContext.Current from within Web service methods. This makes sense if you think of WCF as a service architecture that is independent of ASP.NET since WCF service can be self-hosted, hosted in WAS (Windows Activation Service) or inside of a standard ASP.NET application. If you create a service that can run in multiple hosts, relying on ASP.NET-specific features make sense.

By default, WCF’s REST process when running under ASP.NET hooks into HttpApplication.BeginRequest, which fires very early in the pipeline. If you’ve enabled ASP.NET support, however, the operation occurs as an HttpHandler and so has full access to the ASP.NET intrinsic objects like Session, Cache, and the ASP.NET Configuration Manager to read values out of Web.config, for example.

You can override the behavior to force ASP.NET compatibility of any IIS/ASP.NET hosted WCF service by adding the following tag to your configuration:

<system.serviceModel>
  <serviceHostingEnvironment
     aspNetCompatibilityEnabled="true" />
</system.serviceModel>

You can then add an explicit attribute to your implementation class to make the ASP.NET context available in your application:

[AspNetCompatibilityRequirements
(RequirementsMode = AspNetCompatibilityRequirementsMode.
Allowed)]
public class TimeTrakkerService :
ITimeTrakkerService

For more detail on the ASP.NET Compatibility Mode, check out http://blogs.msdn.com/wenlong/archive/2006/01/23/516041.aspx.

Binary Data and Using WebOperationContext

I’ve talked about the REST services in WCF mainly from an AJAX perspective here by using JSON data. But you can also serve XML data (using ResponseFormat.Xml and RequestFormat.Xml) as well as any generic data via Stream results. Using a stream result from a method returns the raw data to the client using the REST interface. This is useful for things like streaming binary data like images or even raw HTML or other text for some special operations.

In order to return ‘generic’ content rather than JSON or XML you need to specify a few additional pieces of information such as the content type and how the data is returned. To do so you have to use some of the WCF service level context objects rather than using HttpContext.Current to get the Request and Response object.

For example, if you’d like to have an API endpoint to return an image dynamically you can do so with the following code starting with the ServiceContract interface operation:

[OperationContract]
[WebInvoke(Method="GET")]
Stream GetPicture();

And the actual method implementation:

public Stream GetPicture()
{
    string file = Path.Combine(
 HostingEnvironment.ApplicationPhysicalPath,
"bareencoding.jpg");
    
    FileStream fs = new FileStream(
        file,FileMode.Open,FileAccess.Read);
     WebOperationContext.Current.
    OutgoingResponse.ContentType =
                              "image/jpeg";
    return fs as Stream;
}

Using a Stream result lets you return any kind of data which bypasses any of the typical WCF output formatting resulting in raw data going to the client. You can return binary data like images or even text this way:

public Stream GetHtml()
{ WebOperationContext.Current.
    OutgoingResponse.ContentType =
         "text/html; charset=utf-8";
    
    MemoryStream ms = new MemoryStream(
      Encoding.UTF8.GetBytes(
         "<b>Hello World</b>"));
    return ms;
}

Notice the use of WebOperationContext and HostingEnvironment (as well as OperationContext which is not used here) all of which give you information about the WCF environment so you can get access to authentication, the environment, the host, and channel. Using these objects stays within the confines of WCF which means it will work in any hosting environment where HttpContext may not be available.

Roll Your Own?

Finally, if raw AJAX support is what you’re after, you might enjoy the fact that .NET 3.5 ships with a new DataContractJsonSerializer, which provides two-way serialization features for .NET and JSON. With this serializer it’s a cinch to create JSON output and parse JSON strings back into .NET types. With this serializer in place it’s a fairly easy exercise to create your own HttpHandler or ASPX page manager that can take incoming JSON data and route it to a method of a service. You can parse the JSON parameters route to a method, call the method, pick up the result, and serialize the result into a JSON string to return to the client. Or you can simply use a more traditional REST interface to an ASPX page to parse parameters and return responses using non-RPC style coding.

Listing 3 shows some code that demonstrates using the DataContractJsonSerializer.

For what it’s worth you can also use the JavaScriptSerializer in the System.Web.Extensions assembly which is even easier to use and provides a few additional features like the ability to work with object instances for serialization rather than purely with a typed instance as the DataContract serializers do. With the JavaScriptSerializer you can do things like serialize an anonymous type or a variant object, which doesn’t work with DataContractJsonSerializer. The JavaScriptSerializer also offers extensibility to serialize special types like a DataSet that is not natively supported by either serializer.

Are WCF REST Services for You?

If you look closely at the examples above you might ask yourself if it’s really worth going this route for REST calls. It seems like the WCF implementation is actually becoming like a mini Web server implementation that in a lot of ways feels very different than typical WCF service implementations. So wouldn’t it just be easier to create a REST endpoint as an HTTP handler, an MVC Framework View or even an ASPX Web Forms page and have more control over the API?

In the end, WCF’s webHttpBinding is a fancy remote procedure call mechanism that includes all the mechanics to route a request to a specific URL, parse the incoming parameters, call the method of the service class, and return the results, providing robust error handling along the way. It’s not rocket science to build this sort of logic on your own, but WCF provides all of this functionality ready for you to use without any further work. You define your [ServiceContract] and your implementation class with the appropriate methods and it just works.

But WCF limits some of your design choices by not directly supporting polymorphism on the service interfaces, not even through the use of UriTemplates, which is unfortunate. Reuse of service interfaces too is difficult so at the moment it looks like the WCF calls will work best if you only need to serve one kind of client and type of request (ie., only JSON, only XML or only ASP.NET AJAX, only GET or POST but not both, etc.) rather than being able to have one service handle all these endpoints as WCF does with all other service types. This is really unfortunate because in a REST environment the flexibility to access services in a variety of ways is key and adds significant value.

In the end, webHttpBinding provides another nice and easy to use RPC implementation on the server side and if an RPC-style API is what you need to build then webHttpBinding in WCF is a good way to get it done quickly and consistently.