This is the second post on a series about the new Preview 4 of WCF Web API. In the previous post, I introduced the elementary aspects of the programming model, namely: resource classes, operations, HttpRequestMessage and HttpResponseMessage. The main outcome of the post was the TodoResource class.
In this post, I describe how to self-host this class. Lets the code do the talking.
class TheHostProgram
{
static void Main(string[] args)
{
var instance = new TodoResource(new ToDoMemoryRepository());
using (var host = new HttpServiceHost(instance, "http://localhost:8080/todo"))
{
host.Open();
ShowEndpointsOf(host);
WaitForKey();
}
}
private static void ShowEndpointsOf(ServiceHost host)
{
Console.WriteLine("Host is opened with the following endpoints:");
foreach (var ep in host.Description.Endpoints)
{
Console.WriteLine("\tEndpoint: address = {0}; binding = {1}", ep.Address, ep.Binding);
}
}
private static void WaitForKey()
{
Console.WriteLine("Press any key to stop host...");
Console.ReadKey();
}
}
That’s it.
Notice:
- The ShowEndpoints and WaitForKey methods are just utility functions to show the opened endpoints and wait for user input.
- The use of a new service host type – HttpServiceHost.
- For simplicity, the service uses InstanceContextMode.Single. This means that I can pass the resource class instance directly to the service host. This allows me to resolve its dependencies (the IToDoRepository) manually. In a future post, I will show how to use an IoC/DI container to obtain the resource class instances.
- No endpoint has to be explicitly added. The HttpServiceHost automatically adds an endpoint for each defined base address defined in the constructor.
- This default endpoint will have the “http://localhost:8080/todo” base address. Note that the URI templates defined in the resource class are relative to this base address. For instance, a GET request to “http://localhost:8080/todo/123” will be associated with the GetToDo operation (“{id}” template). The template’s id variable will be bound to “123”.
Explicit endpoints can also be added using the old AddServiceEndpoint method, before the service is opened:
host.AddServiceEndpoint(typeof(TodoResource), new HttpBinding(), "http://localhost:8080/todo2");
The host will not add default endpoints if there are explicit endpoints added.
When explicitly adding an endpoint, notice the usage of a new binding – HttpBinding. This is the binding also used in the default endpoints.
Currently, it is even possible to use the old ServiceHost to host a resource class. However, the new HttpBehavior behavior must be added to each endpoint.
var repository = new ToDoMemoryRepository();
repository.Add(new ToDo("Must learn HTTP better"));
var instance = new TodoResource(repository);
using (var host = new ServiceHost(instance))
{
var ep = host.AddServiceEndpoint(typeof(TodoResource), new HttpBinding(), "http://localhost:8080/todo2");
ep.Behaviors.Add(new HttpBehavior());
host.Open();
ShowEndpointsOf(host);
WaitForKey();
}
It is this HttpBehavior and the HttpBinding that “insert” the new WCF Web API model into the WCF runtime. When using HttpServiceHost, this behavior is automatically added.