REST endpoint hosted in a WCF windows service
I have a Windows service that acts as a cache server and is implemented using WCF. This service mainly returns a stream of data dictionaries to it's clients. Recently there was a request for me to make this service more "debuggable". One of the things that was in the TODO list was: be able to query the cache service directly for specific data.
After a lot of thought I decided to expose a REST endpoint to do this job. And belive it or not, it was super easy to do that. And so, I dedicate this blog post about the task.
My existing service was a singleton and implemented an interface such as ICacheService interface. I simply added a new interface called ICacheLookup interface with a method like GetCustomer(int customerId).
1: [ServiceContract(Namespace = "https://MyCompany.CacheServiceLookup")]
2: public interface ICacheLookup
3: {
4: [OperationContract()]
5: [WebGet(UriTemplate="GetCustomer?customerId={customerId}", ResponseFormat=WebMessageFormat.Xml)]
6: Customer GetCustomer(int customerId);
7: }
Next for implementation of this method, I used my singleton CacheService implementation and extracted the customer Id from it.
1: public class CacheLookup : ICacheLookup
2: {
3: public Customer GetCustomer(int customerId)
4: {
5: Customer customer = null;
6: CacheService.Instance.CustomersCache.FullEntities.TryGetValue(customerId, out customer);
7: return customer;
8: }
9: }
After this, all that was left was setting up the configuration endpoint and the rest service startup.
1: <services>
2: <service behaviorConfiguration="ServiceBehavior" name="MyCompany.CacheService">
3: <endpoint address="net.tcp://localhost:2000/CacheService"
4: binding="netTcpBinding" bindingConfiguration="TcpBinding" name="TCP"
5: contract="MyCompany.ICacheService" />
6: </service>
7: <service behaviorConfiguration="ServiceBehavior" name="MyCompany.CacheLookup">
8: <endpoint address="https://localhost:2001/CacheService"
9: binding="webHttpBinding" bindingConfiguration="WebBinding" name="Rest"
10: contract="MyCompany.ICacheLookup" />
11: </service>
12: </services>
Starting the REST service in the ServiceHost:
1: private static ServiceHost service = null;
2: private static System.ServiceModel.Web.WebServiceHost webHost = null;
3:
4: public static void StartService()
5: {
6: Uri baseAddress = new Uri(ConfigurationManager.AppSettings["BaseAddress"]);
7: CacheService serviceInstance = CacheService.Instance;
8: CacheServiceHost.service = new ServiceHost(serviceInstance, baseAddress);
9: CacheServiceHost.service.Open();
10:
11: CacheServiceHost.webHost = new System.ServiceModel.Web.WebServiceHost(typeof(CacheLookup), baseAddress);
12: CacheServiceHost.webHost.Open();
13: }
No changes were needed for deployment, the REST endpoint simply worked and was accessible using the following url:
https://localhost:2001/CacheService/GetCustomer?customerId=2000
That's all, and it was super easy to get xml serialized data out of the service without much ado. Since then I've become a great fan of REST and declarative programming model : )
--Ads by Microsoft--
Comments
Anonymous
March 15, 2009
Thank you for submitting this cool story - Trackback from DotNetShoutoutAnonymous
March 15, 2009
To be considered restful, an endpoint has to be discovered by the client and care needs to be taken in providing correct http caching headers. Good practice would also have you create a new media type, or reuse an existing one using a microformat. More than RESTful, this is POX. Do you have more "endpoings" you've published on that app? It'd be interesting to see if this fits in a wider RESTful architecture or if it's just a one-off POX service.Anonymous
May 08, 2012
Can you share configuration of WebBinding behaviorAnonymous
January 02, 2013
Please share the Web conffig file..i am getting this error: at System.ServiceModel.Dispatcher.InstanceProvider.GetInstance(InstanceContext instanceContext, Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance(InstanceContext instanceContext, Message request) at System.ServiceModel.InstanceContext.GetServiceInstance(Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.EnsureServiceInstance(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)Anonymous
September 15, 2013
Hi brother, Can you share the code in your pages and configuration file, so that how can we write the windows service , we can check. Absolutely no idea of how to host a rest wcf service in windows service.Anonymous
July 20, 2014
Many thanks for your post. After five years :)