How to do it: Developing an WCF Service and host on a Windows Service

Code Samples
Table of Contents
Summary
WCF Service and Hosting on Windows Service Application

WCF Service and Hosting on Windows Service Application

Note

Implementing a WCF Service to be hosted on windows service, the configuration file “App.Config” is only required  on the host project.

Operations
Project "Services.Definition", File "Common.Data.cs"

This file contains the definition of the complex class types sent on the service request and expected as service response

How to do it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace WCF
{
    [DataContract]
    public class Category
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Description { get; set; }
    }
}
Project "Services.Definition", Files "IwcfTestService.cs" and "wcfTestServiceImpl.cs"

The file “wcfTestServiceImpl.cs” represents one implementation of the service contract:

How to do it

The file “IwcfTestService.cs” represents the interface of the service:

using System.ServiceModel;
using System.Collections.Generic;

namespace WCF
{
    #region  "Service definiton using DataContract on resources"

    /// <summary>
    /// Summary description for wcfTestService service contract
    /// </summary>
    [ServiceContract(Namespace="http://www.training.com")]
    public interface IwcfTestService
    {
        [OperationContract]
        Category getCategoryWithDataContractAsXML(string pId);

        [OperationContract]
        Category getCategoryWithDataContractAsJSON(string pId);

        [OperationContract]
        List<Category> getCategoriesWithDataContractAsXML();

        [OperationContract]
        List<Category> getCategoriesWithDataContractAsJSON();

        [OperationContract]
        int addCategoryWithDataContractAsXML(Category pCategory);

    #endregion

        #region  "Service definiton without using DataContract on resources"

        [OperationContract]
        string getCategoryAsXML(string pId);

        [OperationContract]
        string getCategoryAsJSON(string pId);

        [OperationContract]
        List<string> getCategoriesAsXML();

        [OperationContract]
        List<string> getCategoriesAsJSON();

        [OperationContract]
        int addCategory(string pName);

        #endregion

    }
}

The file “wcfTestServiceImpl.cs” represents one implementation of the service contract:

using System.Collections.Generic;
using System;

namespace WCF
{
    /// <summary>
    /// Summary description for wcfTestService service contract implementation
    /// </summary>
    public class wcfTestServiceImpl : IwcfTestService
    {

        #region  "Service definiton without using DataContract on resources"

        public string getCategoryAsXML(string pID)
        {
            //TODO: Put code here to retrieve category name...
            return loadCategory(Convert.ToInt32(pID));
        }

        public string getCategoryAsJSON(string pID)
        {
            //TODO: Put code here to retrieve category name...
            return loadCategory(Convert.ToInt32(pID));
        }

        public List<string> getCategoriesAsXML()
        {
            //TODO: Put code here to retrieve category names...
            return loadCategoryNames();
        }

        public List<string> getCategoriesAsJSON()
        {
            //TODO: Put code here to retrieve category names...
            return loadCategoryNames();
        }

        public int addCategory(string pName)
        {
            //TODO: Put code here to save category name
            return 10;
        }

        private string loadCategory(int pId)
        {
            return "This the category with name for ID " + pId.ToString();
        }

        private List<string> loadCategoryNames()
        {
            return new List<string>() { "Category #1", "Category #2" };
        }
        #endregion

        #region  "Service definiton using DataContract on resources"
        public Category getCategoryWithDataContractAsXML(string pId)
        {
            //TODO: Put code here to retrieve category...
            return loadCategoryWithDataContract(Convert.ToInt32(pId));
        }

        public Category getCategoryWithDataContractAsJSON(string pId)
        {
            //TODO: Put code here to retrieve category...
            return loadCategoryWithDataContract(Convert.ToInt32(pId));
        }

        public List<Category> getCategoriesWithDataContractAsXML()
        {
            //TODO: Put code here to retrieve category names...
            return loadCategoriesWithDataContract();
        }

        public List<Category> getCategoriesWithDataContractAsJSON()
        {
            //TODO: Put code here to retrieve category names...
            return loadCategoriesWithDataContract();
        }

        public int addCategoryWithDataContractAsXML(Category pCategory)
        {
            //TODO: Put code here to save category defintion
            return 10;
        }

        private Category loadCategoryWithDataContract(int pId)
        {
            return new Category { Id = 1, Name = string.Format("category #{0}", pId), Description = string.Format("test category #{0}", pId) };
        }

        private List<Category> loadCategoriesWithDataContract()
        {
            return new List<Category>() {
                            new Category { Id=1, Name="category #1", Description= "test category #1"},
                            new Category { Id=2, Name="category #2", Description= "test category #2"} };
        }
        #endregion

    }
}
Project "wcfWindowsServiceHost", Files "wcfWindowsService.cs" e installer "wcfWindowsServiceInstaller.cs"
How to do it

The file “wcfWindowsService.cs” represents the host implementation on a windows service:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;

namespace WCF
{
    public partial class wcfWindowsService: ServiceBase
    {
        ServiceHost m_serviceHost;

        public wcfWindowsService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            m_serviceHost = new ServiceHost(typeof(WCF.wcfTestServiceImpl));
            m_serviceHost.Open();
        }

        protected override void OnStop()
        {
            if (m_serviceHost != null)
            {
                m_serviceHost.Close();
            }
            m_serviceHost = null;
        }
    }
}

The file “wcfWindowsService.cs” represents the installer of the windows service:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace wcfWindowsServiceHost
{
    [RunInstaller(true)]
    public partial class wcfWindowsServiceInstaller : System.Configuration.Install.Installer
    {
        public wcfWindowsServiceInstaller()
        {
            InitializeComponent();
            ServiceProcessInstaller processInstaller = new ServiceProcessInstaller();
            ServiceInstaller serviceInstaller = new ServiceInstaller();
            processInstaller.Account = ServiceAccount.LocalSystem;
            serviceInstaller.DisplayName = "WCF Windows Service (Training)";
            serviceInstaller.Description = "WCF Windows Service (Training)";
            serviceInstaller.ServiceName = "WCF Windows Service";
            serviceInstaller.StartType = ServiceStartMode.Manual;
            Installers.Add(processInstaller);
            Installers.Add(serviceInstaller);
        }
    }
}
Project "wcfConsoleApplicationHost", File "App.config"

The configuration file configures :

  • service endpoints to use (address, contract implementation and binding);
  • host base address service endpoints;
How to do it
<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="defaultServiceBehavior" name="WCF.wcfTestServiceImpl">
        <endpoint address=""  behaviorConfiguration="" binding="wsHttpBinding" contract="WCF.IwcfTestService">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address=""  binding="netTcpBinding" contract="WCF.IwcfTestService"/>
        <endpoint address="mex" bindingConfiguration="" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:55546/training/wcf/ws/testservice1"/>
            <add baseAddress="net.tcp://localhost:8000/training/wcf/ws/testservice1"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <endpointBehaviors>
        <behavior name="webEndPointBehavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="defaultServiceBehavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>