Anatomy of a simple REST service

I want to discuss some interesting topics about services, notably service versioning. Let me start by looking at a very simple REST service using WCF Web HTTP services, creating one to explore how it is put together.

Creating a service application

Start by creating a new WCF Service Application project in Visual Studio with File | New | Project | Visual C# | WCF | WCF Service Application and name it AcmePaint. In the Solution Explorer, delete the generated Service1.svc and IService1.cs files.

Creating a DTO

Add a class named Color. This class is a Data Transfer Object (DTO) whose singular goal should be to represent the service’s message as it is transferred from one process to another. This class is responsible for the shape of “the message on the wire.”

public class Color
{
  public byte Red { get; set; }
  public byte Green { get; set; }
  public byte Blue { get; set; }
}

Adding a WCF service

Right-click on the project in the Solution Explorer and select Add | New Item | Visual C# | Web | WCF Service and name it Colors.svc.

Writing the service contract

The service contract is expressed as an the interface IColors with the [ServiceContract] attribute; that part hasn’t changed since WCF was introduced. Edit the IColors interface to define two operations like this.

using System.ServiceModel;
using System.ServiceModel.Web;

namespace AcmePaint
{
  [ServiceContract]
  public interface IColors
  {
    [WebGet( UriTemplate = "Color/{id}" )]
    Color GetColor( string id );

    [WebInvoke( Method = "POST", UriTemplate = "Color" )]
    void PostColor( Color color );
  }
}

The GetColor method is our archetypal method for performing an HTTP request with the GET verb. The [WebGet] attribute tells the WCF infrastructure that this method is invoked using GET, and the UriTemplate named parameter declares the structure of the URL. The id parameter is written in curly braces which declares that its value in the URL will be passed to the method each time the method is invoked.

The PostColor method is our archetypal method invoked using an HTTP request with the POST verb as declared with the [WebInvoke( Method = “POST” )] attribute. Here UriTemplate declares that it uses the same resource name, Color, as the GetColor method, just without any following URL parts.

Note that both methods use the Color class for the resource sent (POST) and received (GET) by the service’s client.

Writing the service implementation

Edit the Colors class in Colors.svc.cs which implements the IColors interface. You can get to this file by double-clicking on the Colors.svc entry in the Solution Explorer. I am going to be focusing on getting data in and out of a service, so the implementations here are intentionally bare bones.

namespace AcmePaint
{
  public class Colors : IColors
  {
    public Color GetColor( string id )
    {
      // retrieve the color from its id here...

      return new Color { Red = 0xff, Green = 0x80, Blue = 0x00 };
    }

    public void PostColor( Color color )
    {
      Color requestedColor = color; // illustrate the type of color parameter

      // do something with color here...
    }
  }
}

Inspecting the .svc file

In the Solution Explorer, right-click on Colors.svc and select View Markup. You should see that it s a one-liner containing the following.

<%@ ServiceHost Language="C#" Debug="true" Service="AcmePaint.Colors" CodeBehind="Colors.svc.cs" %>

Aside from declaring the implementation language and enabling debugging, this file associates a service name, AcmePaint.Colors, with a source code file containing the class that implements the service. We’ll see that service name again in our next step.

Configuring the service

Open the Web.config file and replace its contents with the following.

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.serviceModel>

    <services>
      <service name="AcmePaint.Colors">
        <endpoint address=""
                  contract="AcmePaint.IColors"
                  kind="webHttpEndpoint"/>
      </service>
    </services>

    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name=""
                          helpEnabled="true"
                          defaultOutgoingResponseFormat="Json"/>
      </webHttpEndpoint>
    </standardEndpoints>

  </system.serviceModel>

</configuration>

The <service> element declares the service name using the same value we saw in the Colors.svc file.

Inside of that element we declare a service endpoint. The address attribute is empty which means that the endpoint address will just be the address of the Colors.svc service. The contract attribute names the interface that is our service contract. And the kind attribute declares this endpoint to be a standard web HTTP endpoint, which uses a fixed webHttpBinding. That is a binding configures endpoints to respond to HTTP requests instead of SOAP messages.

The standardEndpoint element has an empty name, making this the default for all webHttpEndpoints. We’ve used this default to enable help and to set the default format for outgoing response messages to be JSON..

Selecting hosting options

In the AcmePaint project in the Solution Explorer, double-click on the Properties item to display the AcmePaint properties window. Select the Web tab. In the Servers section, verify that Use Visual Studio Development Server is selected.

(If you have IIS installed on your local workstation, you could use the option to Use Local IIS Web Server instead.)

Running the service

In the Solution Explorer, select the AcmePaint project, then press F5 to run the project in debug mode.

Selecting a node in the Solution Explorer first is important! Otherwise, e.g., if you have the Colors.svc.cs file open and selected (active), then pressing F5 to run will launch the WCF Test Client which will display an error because this service is not exposing metadata.

Be patient for a moment while the ASP.NET Development Server starts up, and then your browser will launch a page with the URL http://localhost:xxxx/ where xxxx is the auto-assigned port number that was listed on the AcmeProject Properties page where you selected to use the Visual Studio Development Server.

restservicedirectorylisting

In the browser address bar, edit the URL to read http://localhost:xxxx/Colors.svc/help, using the same port number for xxxx as before. This is the help page that we enabled in configuration.

restservicehelppage

One last time edit the URL in the browser address bar, this time to read http://localhost:xxxx/Colors.svc/Color/42, with xxxx as before. This time the browser prompts whether you was to Open, Save or Cancel the response. Select Open. In the Open With dialog, select Notepad | OK. In the Open File dialog select Open. The following JSON is displayed in Notepad

{"Blue":0,"Green":128,"Red":255}

Cleaning up

Close the browser to stop debugging the service.

Review

We created a minimal REST service and used a browser as an impromptu client to GET a resource, with the response data being delivered as JSON.

Resources

Download the completed code

Comments are closed.