Creating a Restful WCF service in .NET is pretty easy (once you’ve sorted through the myriad of confusing VS2010 options).

Here’s one way simple way to do it.

Step 1: Create a new plain old C# library.

Fire up Visual Studios 2010, create a blank solution, and add a plain old C# library called ‘Services’.

Step 2: Define your Restful service and Dto.

To create a Restful WCF service that handles a GET request, define the following interface and implementation.

IInvoiceService.cs

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

namespace Services
{
    [ServiceContract]
    public interface IInvoiceService
    {
        [WebGet(UriTemplate = "/invoices")]
        [OperationContract]
        InvoiceDto[] GetAllInvoices();
    }
}

InvoiceService.cs

namespace Services
{
    public class InvoiceService : IInvoiceService
    {
        public InvoiceDto[] GetAllInvoices()
        {
            return new[] { new InvoiceDto(1, "receiver1"), new InvoiceDto(2, "receiver2") };            
        }
    }
}

To import these attributes you’ll need to add references to System.ServiceModel and System.ServiceModel.Web

Then add your Dto. Dto’s need to be marked up with DataContract and DataMember attributes so they can be serialized by WCF.

InvoiceDto.cs

using System.Runtime.Serialization;

namespace Services
{
    [DataContract(Namespace = "")]
    public class InvoiceDto
    {
        public InvoiceDto(int id, string receiver)
        {
            Id = id;
            Receiver = receiver;
        }

        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Receiver { get; set; }
    }
}

Step 3: Host it.

There’s lots of ways to host a WCF restful service. We could create a console application and host it there. We could create a new full on ASP.NET website (WCF enabled) and host it there.

But for simplicity (and because this is how we are trying it in our project) create a ‘WCF Service Application’ and host it there in a project call ‘Host’.

Our new Host project comes with a svc file. This file just sits in the IIS (or Cassini) virtual directory and points to the service it supports. You have one svc file per service.

In our case, we don’t need the default Service1 that came with the application (so go ahead and delete those).

Instead, edit the Service1.svc file and point it too the service we just created in our plain old C# library.

Service.svc

<%@ ServiceHost Service="Services.InvoiceService" Factory="System.ServiceModel.Activation.WebServiceHostFactory"  %>

This WebServiceHostFactory is a new class introduced in WCF 3.5 purely for making WCF services restful. By using it, we don’t need any WCF configuration in our webconfig file.

In fact for the purpose of this demo we can completely gut it and leave it empty as shown below.

Host/web.config

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

Step 4: Test it in the browser.

Now if everything is working, we should be able to right click on Service1.svc in our hosted project and go ‘View in browser.

This will fire up Cassini and display a blank page with the message ‘End point not found’. That’s OK.

The real test for us is when we add on the restful GET extension ‘/invoices’ to the URL. When we do that, we should get something like this:

http://localhost:49619/Service1.svc/invoices

Something to be aware of …

Now if you like WCF, and are thinking of building your next application using Restful WCF service, beware of one big gotcha.

You can’t autogenerate client side proxies using WCF.

Rest (HTTP) doesn’t knew anything about WSDL (the SOAP contract used by Visual Studios to create the proxies).

It can’t automatically create proxies for you like regular WCF. This might change in future versions of WCF (which Microsoft has indicated are going to be way more Restful). But for for now, to call this service from a unit test, you have to hand role your own proxy, or just work with basic .NET Http constructs like WebHttpRequest and WebHttpResponse as shown below.

using System.Net;
using NUnit.Framework;

namespace Test
{
    [TestFixture]
    public class When_calling_a_restful_service
    {
        [Test]
        public void Should_get_proper_HTTP_codes_and_headers()
        {

            var url = "http://localhost:49619/Service1.svc/invoices";
            var request = (HttpWebRequest)WebRequest.Create(url);
            var response = (HttpWebResponse)request.GetResponse();

            Assert.AreEqual(200, (int)response.StatusCode);
        }

    }
}

This isn’t the end of the world. On one hand your proxies are always up to sync (because there are none). On the other you just need to track URLs and figure out how to tell your client where your services live.

These are some of the things we’re learning as we spike out some Silverlight Rstful implementation stuff with WCF. Would love to hear about any more insights or gotchas as we definitely haven’t figured it all out.

Advertisements