Today I am going to show you how to host a WCF service in a managed environment such as windows service. Let us see how to achieve this through C#.
Here, I will first show you how to create a simple windows service and then how to host a WCF service in it.
I will also show you how to pass the external messages received on this service, to a host. I am going to use a singleton pattern to avoid the race condition while receiving messages concurrently.
- Create a “Console Application” project named as “SelfHostService” using installed templates in Visual Studio
- Delete Program.cs file from project
- Add a new class named as SelfHostService.cs
- Click Add Reference menu to open a Add Reference Dialog Box
- Select
System.ServiceProcess
namespace to refer ServiceBase
class resides in this newly added namespace, which is required to create a service application. DeriveSerivceBase
class inSelfHostService
class- Also add a reference to
System.ServiceModel
namespace - Now let us put some code in
SelfHostService
class - In above code I have created a public property named
Instance
to provide a single instance ofSelfHostService
class - Now let us define a service contract
IMessageListener
- We will have to override
OnStart()
andOnStop()
methods ofServiceBase
class. These methods contains instructions to follow when service starts and stops respectively. Let us write a code for these methods DoWork
method is a task assigned to a timer which has been initialized inOnStart()
method. After every interval elapses, this method will get executed. So one can write any code which is to be performed repetitively by a window service.- I will add a method to accept requests, received by
MessageListenerService
- Now we will implement
IMessageListener
inMessageListenerService
- We will have to configure the services’ base address, binding and contracts
public class SelfHostService : ServiceBase { public ServiceHost serviceHost = null; private bool startProcessing; private static SelfHostService instance = null; private static readonly object padlock = new object(); //a private constructor SelfHostService() { ServiceName = "Self Hosted Service"; } //public static property to access the instance of the SelfHostService class public static SelfHostService Instance { get { lock (padlock) { if (instance == null) instance = new SelfHostService(); return instance; } } } }
namespace SelfHostService { public interface IMessageListener { bool AcceptMessages(string messsage); } }
protected override void OnStart(string[] args) { if (serviceHost != null) serviceHost.Close(); serviceHost = new ServiceHost(typeof(MessageListenerService)); serviceHost.Open(); var timer = new Timer(); timer.Interval = 60000; timer.Elapsed += new ElapsedEventHandler(DoWork); timer.Start(); } protected override void OnStop() { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } }
private void DoWork(object sender, ElapsedEventArgs e) { //Add code to do the intended work }
public bool AcceptExternalMessages(string message) { if (string.IsNullOrEmpty(message)) return false; else return true; }
public class MessageListenerService : IMessageListener { public bool AcceptMessages(string message) { //Notify message to windows service return SelfHostService.Instance.AcceptExternalMessages(message); } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="SelfHostService.MessageListenerService" behaviorConfiguration="ServiceBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8082/SelfHostService/Service"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="SelfHostService.IMessageListener" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior" > <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
In my next post I will write about how to install this service using InstallUtil.exe
Note: This code post is written in C# 6.0 in Visual Studio 2015