Getting started with the WCF Web API

Warning: This post is based on a prerelease version of the WCF Web API

 

When designing services the REST style is becoming more and more popular. Not that REST is anything new, it has been around for some time. The fact that WCF supports REST services isn’t new either as the WebServiceHost and WebHttpBinding where released with the .NET framework 3.5. However the original REST support in WCF was quite limited. You could build very nice REST services but you had to do a lot of work because out of the box there isn’t support for much functionality.

 

Enter the WCF Web API

The new Web API is supposed to change that and enable a lot more flexibility to create more powerful REST services using WCF. At the moment the Web API is still in a preview state so things might change quite a bit before it is actually released so keep that in mind if you read this some time in the future.

 

The current WCF REST Model

The current WCF REST model is based on the WebHttpBinding and a convenience WebServiceHost. These make it very easy to create and host a REST service. The basic code for a very simple service looks something like this:

class Program


{


    static void Main(string[] args)


    {


        var host = new WebServiceHost(typeof(PeopleService), new Uri("http://localhost:8080/people"));


 


        host.Open();


 


        foreach (var ep in host.Description.Endpoints)


        {


            Console.WriteLine("Using {0} at {1}", ep.Binding.Name, ep.Address);


        }


 


        Console.ReadLine();


 


        host.Close();


 


    }


}


 


 


[ServiceContract]


class PeopleService


{


    [WebGet(UriTemplate = "{id}")]


    Person GetPerson(string id)


    {


        var person = GetPeople().SingleOrDefault(p => p.Id.ToString() == id);


        return person;


    }


 


    [OperationContract]


    [WebGet(UriTemplate = "")]


    List<Person> GetPeople()


    {


        var people = new List<Person>()


                     {


                         new Person()


                             {


                                 Id = 1,


                                 FirstName = "Maurice",


                                 LastName = "de Beijer",


                             },


                     };


        return people;


    }


}

 

The equivalent service using the WCF Web API is very similar. Instead of the WebServiceHost/WebHttpBinding we can use the HttpServiceHost/HttpBinding and things will just work. Changing the Main to the following is all that is required:

static void Main(string[] args)


{


    var host = new HttpServiceHost(typeof(PeopleService), "http://localhost:8080/people");


 


    host.Open();


 


    foreach (var ep in host.Description.Endpoints)


    {


        Console.WriteLine("Using {0} at {1}", ep.Binding.Name, ep.Address);


    }


 


    Console.ReadLine();


 


    host.Close();


}

So getting started is easy Smile

Pointing the browser at the base address produces exactly the same result as it would have with the WebServiceHost

image

 

So if changing is so easy but gives us exactly the same why bother?

Well the original WCF REST support was quite limited. For example by default we could only work with XML or JSON messages. And normally that was done by changing the WebGet attribute. And doing other things with the response often required us to use the static WebOperationContext.Current making out code much harder to unit test.

With the new Web API we can use input parameters and return values to get more control the HTTP request and response, much more testable. And it supports content negotiation so we can do much more than just XML and JSON without all the trouble we had to go through before. More about this content negotiation in a future blog post.

 

Improving on the getPreson operation using the Web API

Currently the GetPerson operation takes a string input parameter named id. This was a requirement for the old model, all input parameters had to be of type string with a get request. With the Web API this is no longer the case and I can change it to an integer as I would really have wanted to in the first place. A nice change but by itself not a big deal.

Suppose we invoke the GetPerson operation with an invalid ID. In that case we would like to have some more control over the response and return an HTTP 404 Not Found response. With the new model that is easy. Instead of returning a Person object we can also return an HttpResponseMessage<Person> letting us set addition HTTP response settings. By changing the GetPerson operation to the following we do just that.

[WebGet(UriTemplate = "{id}")]


HttpResponseMessage<Person> GetPerson(int id)


{


    var person = GetPeople().SingleOrDefault(p => p.Id == id);


    var response = new HttpResponseMessage<Person>(person);


 


    if (person == null)


    {


        response.StatusCode = HttpStatusCode.NotFound;


    }


    return response;


}

And we could set the status to Created or any other reasonable value exactly the same way. Suppose I wanted to show the complete list of people when an invalid one was requested doing a redirect is just as easy with the following code:

[WebGet(UriTemplate = "{id}")]


HttpResponseMessage<Person> GetPerson(int id)


{


    var person = GetPeople().SingleOrDefault(p => p.Id == id);


    var response = new HttpResponseMessage<Person>(person);


 


    if (person == null)


    {


        response.StatusCode = HttpStatusCode.RedirectMethod;


        response.Headers.Location = new Uri("http://localhost:8080/people");


    }


 


    return response;


}



Granted this is not very likely to be the required behavior but it does demonstrate the power of the Web API and being able to return a HttpResponseMessage<T>.



 



With this example I used a console application to host our REST service. That is very nice and sometimes useful but hosting a service in IIS is far more common so in a next blog post I am going to show how to host a Web API REST service in an ASP.NET MVC web site, something that is far more common.



 



Enjoy!



[f1]
[f2]

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>