WCF Service Hosting Made Easy

I often hear that WCF is hard to work with because it needs so much configuration. That might have been true in .Net 3.5, but since .Net 4.0 <serviceActivations> has been around to make our lives easier. Today, .Net 4.0 is not far from the Stone Age… So I am surprised that this is still an issue.

To get started simply:

  1. Create empty ASP.Net Web Application
  2. Add reference to System.ServiceModel.dll
  3. Add the <system.serviceModel> tag from the snippet below in your Web.config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<protocolMapping>
<clear />
<add scheme="net.pipe" binding="netNamedPipeBinding" />
<add scheme="net.tcp" binding="netTcpBinding" />
<add scheme="http" binding="basicHttpBinding" />
</protocolMapping>
<serviceHostingEnvironment>
<serviceActivations>
<add service="Example.Wcf.MyService" relativeAddress="./myservice.svc"
factory="System.ServiceModel.Activation.ServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
</configuration>

You now have a convenient way to host WCF services by adding references to all Class Libraries that contain your service implementations. To get the Service Hosting Environment to pick up your services, all you have to do is to point them out with an extra <add /> under <serviceActivations>.

This approach has a number of advantages:

  • The hosting code is close to zero, which makes it easy to reach 100% code coverage through unit testing.
  • All services automatically gets endpoints over many protocols, which makes the information flow in your application more configurable.
  • In addition to the service implementation, there is no need for metadata files just to make hosting possible.

Below is an example of a service implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.ServiceModel;

namespace Example.Wcf
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
int Add(int x, int y);
}

public class MyService : IMyService
{
public int Add(int x, int y)
{
return x + y;
}
}
}

IoC

To make it easier to test the services that I write, I often use IoC containers of some sort to handle dependency resolution. The default ServiceHostFactory does not let you configure the container.

To do this with Unity you can replace the factory with a UnityServiceHostFactory, which can be found in the NuGet-package Unity.Wcf.

Client Proxies

Please do not use WCF clients generated with Add ? Add Service Reference… They are hard to maintain and dispose of correctly.

One way to create a proxy to a WCF service is to inherit ClientBase<T>. It works pretty well, except that someone at Microsoft must have made a mistake when implementing its Dispose functionality. Or more precise, its lack of. According to their recommendations; to be sure to close the proxy once you are done using it, the client code should be bloated with enormous try-catch blocks.

What is natural for me is to use using-blocks, but apparently this is not possible without some customization.

Custom Client Proxy

Out on the ?internet?, there exists many suggestions how to do this. What has been working for me is to use the following wrapper around the ClientBase<T>.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace Example.Wcf
{
public interface IServiceClient<T> : IDisposable where T : class
{
T Proxy { get; }
}

public class ServiceClient<T> : IServiceClient<T> where T : class
{
private class ClientProxy<TChannel> : ClientBase<TChannel> where TChannel : class
{
public ClientProxy()
{
}

public ClientProxy(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress)
{
}

public TChannel Proxy
{
get { return Channel; }
}
}

private bool _disposed;
private readonly ClientProxy<T> _clientProxy;

public ServiceClient(Binding binding, EndpointAddress remoteAddress)
{
_clientProxy = new ClientProxy<T>(binding, remoteAddress);
}

public ServiceClient()
{
_clientProxy = new ClientProxy<T>();
}

public T Proxy
{
get { return _clientProxy.Proxy; }
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (!disposing)
return;
if (_clientProxy.State == CommunicationState.Faulted)
{
_clientProxy.Abort();
return;
}
try
{
_clientProxy.Close();
}
catch
{
_clientProxy.Abort();
}
_disposed = true;
}

~ServiceClient()
{
Dispose(false);
}
}
}

With it you can either provide the client configuration in your App/Web.config like so:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.pipe://localhost/Example.Wcf/myservice.svc"
binding="netNamedPipeBinding" contract="Example.Wcf.IMyService" />
</client>
</system.serviceModel>
</configuration>

Or inject it manually in the ServiceClient(Binding, EndpointAddress) constructor.

How do you use prefer to use WCF clients?

Project Example