Chris's coding blog

Configuring WCF in code

May 06, 2015

One of the main issues I have with WCF, compared to say a WebApi or a NancyFX based API, are the ridiculously large configuration options you have available. The ABC approach it uses (addresses, bindings, contracts) can adds a lot of confusion when you’re creating a service and also connecting with a client.

WCF was designed as a replacement for COM+ and has a lot of ‘enterprisey’ uses that a REST api doesn’t, such as MSMQ support and named pipes - there’s an interesting discussion on its merits vs NServiceBus here - but with all these extra configuration options you have the usual Microsoft preference of crow barring it all into XML, their favourite overly-verbose markup format.

If you want a good example of how XML isn’t the solve-all format for everything, just look at an MSBuild project versus a Travis CI (YAML) description file. XML is great for providing structured data between services but for configuration I would argue it’s terrible, as you want configuration options to be readable and editable quickly, and it looks like Microsoft are heading away from XML in vNext anyway and onto JSON.

So a giant WCF XML configuration section in your web.config could look something like this:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyNameSpace.ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="applicationServiceSettings" maxReceivedMessageSize="5242880" />
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
<services>
<service behaviorConfiguration="MyNameSpace.ServiceBehavior" name="MyNameSpace.PizzaService">
<endpoint address="" binding="basicHttpBinding" contract="MyNameSpace.IPizzaService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>

In .NET 4 you can actually remove the services section

In .NET Framework 4, the element is optional. When a service does not define any endpoints, an endpoint for each base address and contract implemented are added to the service.

You let WCF create all the defaults for you, getting a leaner web.config:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyNameSpace.ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
view raw simplewcf.xml hosted with ❤ by GitHub
However, for the most part you will always be using WCF in the same way so having all of this in C# is a lot more expressive and easier for project templates. This is its equivalent in C#, note the magical public static void Configure(ServiceConfiguration config) which is called by the framework in every service you create:

public class Configuration
{
public static void ConfigureForHttp<T>(ServiceConfiguration config)
{
var existingBehaviour = config.Description.Behaviors.FirstOrDefault(x => x is AspNetCompatibilityRequirementsAttribute);
if (existingBehaviour != null)
{
config.Description.Behaviors.Remove<AspNetCompatibilityRequirementsAttribute>();
}
config.Description.Behaviors.Add(new AspNetCompatibilityRequirementsAttribute { RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed });
config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
config.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
config.EnableProtocol(new BasicHttpBinding());
config.EnableProtocol(new BasicHttpsBinding());
//config.EnableProtocol(MetadataExchangeBindings.CreateMexHttpBinding());
config.AddServiceEndpoint(typeof(T), new BasicHttpBinding() { MaxReceivedMessageSize = 5242880 }, "basic");
}
}
// Example usage:
public class PizzaService : IPizzaService
{
public static void Configure(ServiceConfiguration config)
{
Configuration.ConfigureForHttp<IPizzaService>(config);
}
public void OrderPizza(string toppings)
{
}
}

xmlwcf

I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via GithubStackoverflowResume