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.
Pingback: HTTP content classes « Pedro Félix’s shared memory
Pedro, did you use a Project type of Console Application to host your ToDoResource? I’ve developed an wcf web application using the ASP.NET Web application type and have tried to host it from a WCF Service app and Console app but I can’t resolve dependencies for the HTTPService host etc. I also tried just adding a Resource class to a WCF Service app but the Nuget wcf web api package fails to install. Obviously, new ground for me; I appreciate any advice. Thanks.
It seems to me that you’d either use HttpServiceHost OR HttpListener, but not both. What is the difference between them? Is there any documentation on these WebAPI classes?
When I dove in to WebAPI, I landed in HttpListener, but I’m having trouble in that my responses are not getting their headers written – we’re just jumping straight to the body.