Simple WCF

[Für Details siehe meinen kommenden Artikel “WCF Leicht und robust” im dotnetpro Magazin 1/2016.]

Choosing WCF options and configuring them can be quite cumbersome and demanding. This post shares a very simple approach for using WCF services. Download complete code. My simple approach uses:

  • Shared Interface-DLL
  • Self-hosting in a Windows Service.
    See Windows Service Worker Options.
  • Channel proxies instead of ClientBase proxies.
  • Simplified WCF configuration.
  • Custom method CreateChannel().
    Caching ChannelFactories.
  • Custom method CloseChannel().
    Handling Channel failures.

I am using a new Channel instance for each WCF call. This improves robustness against communication problems and against “The socket connection was aborted” exceptions after a client idle time > 10 min (= default ReceiveTimeout) with netTcpBinding even when using InstanceContextMode=PerCall.

Simple WCF solution

Complete WCF  client and service code including configuration:

[--Client--]
  Public Class Form1
    Private Sub btnEcho_Click(sender As Object, e As EventArgs) Handles btnEcho.Click
        Dim svc = CachedChannelFactory.CreateChannel(Of IWCFService1Lib.IWCFService1)()
        Try
            Dim echo = svc.Echo(TextBox1.Text)
            ListBox1.Items.Add(echo)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            CachedChannelFactory.CloseChannel(svc)
        End Try
    End Sub
  End Class

' <configuration>
'  <system.serviceModel>
'   <client>
'     <endpoint name=""
'               address="net.tcp://localhost:8731/TestService1"
'               binding="netTcpBinding" 
'               contract="IWCFService1Lib.IWCFService1">

[--Interface DLL IWCFService1Lib--]
  <ServiceContract(Namespace:="urn:leanwork.net/demos/simplewcf/201504")>
    Public Interface IWCFService1
      <OperationContract()>
      Function Echo(msg As String)

[--Windows  Service Host--]
Public Class WinService1
    Private _wcfHost As ServiceHost

    Protected Overrides Sub OnStart(ByVal args() As String)
        _wcfHost = New ServiceHost(GetType(WCFService1))
        _wcfHost.Open()
    End Sub

[--WCF Service--]
' <configuration>
'     <services>
'       <service name="WindowsService1.WCFService1">
'         <host>
'           <baseAddresses>
'             <add baseAddress="net.tcp://localhost:8731/TestService1"/>

  Public Class WCFService1
    Public Class WCFService1 : Implements IWCFService1Lib.IWCFService1
       Public Function Echo(msg As String) Implements IWCFService1Lib.IWCFService1.Echo
         Return DateTime.Now & " " & msg
       End Function
    End Class

CachedChannelFactory

  • CreateChannel Creates a new Channel form cached ChannelFactories. Caching is implemented in a one-liner using ConcurrentDictionary.GetOrAdd().
  • CloseChannel Allows using a service proxy via a Try/Finally block instead of a Using-Block. See MSDN, Avoiding Problems with the Using Statement
Public Class CachedChannelFactory
    Private Shared _channelFactoryCache As New ConcurrentDictionary(Of String, ChannelFactory)

    Public Shared Function CreateChannel(Of T)() As T
        Dim fac As ChannelFactory(Of T) = _channelFactoryCache.GetOrAdd(
                                                GetType(T).ToString,
                                                New ChannelFactory(Of T)(""))
        Return fac.CreateChannel()
    End Function

    Public Shared Sub CloseChannel(channel As IClientChannel)
        If channel Is Nothing Then Return
        Try
            channel.Close()
        Catch __ As CommunicationException
            channel.Abort()
        Catch __ As TimeoutException
            channel.Abort()
        Catch __ As Exception
            channel.Abort()
            Throw
        End Try
    End Sub
End Class

Multiple WCF Services in a Windows Service

Hosting many WCF services in a single Windows service for finer modularization:

List _serviceTypes = new List() {
                typeof(WCFService1),
                typeof(WCFService2),
                typeof(WCFService3),
                };
List _serviceHosts = new List();

…
protected override void OnStart(string[] args)

  _serviceTypes.ForEach(type =>
  {
    var rootUrl = ConfigurationManager.AppSettings["AllServicesRootUrl"] as string;
    Uri[] baseAddresses = { new Uri(Url.Combine(rootUrl, type.Name)) };
    var host = new ServiceHost(type, baseAddresses);
    host.Open();
    _serviceHosts.Add(host);
    host.ChannelDispatchers.ToList().ForEach(x =>
            _trace.InfoFormat("WCF listening on: {0}", x.Listener.Uri));
  });

About Peter Meinl

IT Consultant
This entry was posted in Computers and Internet and tagged , , , . Bookmark the permalink.

One Response to Simple WCF

  1. Pingback: Thoughts and Experiments about Cloud Encryption | Peter Meinl: Software Development Tips

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s