Wednesday, October 24, 2012

.NET 4.5 - Simplified WCF Configuration

A WCF configuration file is basically a markup file used to communicate to the hosting environment how a WCF service is configured and should behave.  The configuration files have historically required an exhaustive explanation of each aspect of configuration and behavior.  To illustrate this, consider a standard config file.  Notice that the file contains a <system.serviceModel> section which contains a <service> element for each service hosted.  The <service> element contains a listing of <endpoint> elements that outline the endpoints for each service and a set of service behaviors.  The <endpoint> elements specify the address, binding and contract exposed by the endpoint, and optional binding and endpoint configuration.  The <system.serviceModel> section also contains a <behaviors> element that allows you to specify service or endpoint behaviors.  The following example shows the <system.serviceModel> section of a configuration file.
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true">
        <serviceDebug includeExceptionDetailInFaults="false">
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
   <basicHttpBinding>
      <binding name=MyBindingConfig"
               maxBufferSize="100"
               maxReceiveBufferSize="100" />
   </basicHttpBinding>
   </bindings>   <services>
    <service behaviorConfiguration="MyServiceBehavior"
             name="MyService">
      <endpoint address=""
                binding="basicHttpBinding"
                contract="ICalculator"
                bindingConfiguration="MyBindingConfig" />
      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange"/>
    </service>
  </services>
</system.serviceModel>
In 4.5, the configuration has been simplified by no longer requiring a <service> element.  When the <service> section is absent, or a <service> section defines no endpoints (and your service does not programmatically define any endpoints), default endpoints with default configurations are automatically added to each service.  These defaults are added for each service base address and for each contract implemented by the service.  In the default endpoints, the endpoint address relates the base address, the binding is determined by the base address scheme and the contract is the one implemented by the service.

To take this further, if you have no need to specify endpoints, modify behaviors or customize the binding, The config file is not needed at all.  For example, if a service implements x contracts and the host enables both HTTP and TCP, the service host creates x*2 default endpoints as a straight contract:endpoint.  To create default endpoints the service host must know what bindings to use.  These settings are specified in a <protocolMappings> section within the <system.serviceModel> section.  The <protocolMappings> section contains a list of transport protocol schemes mapped to binding types.  The service host uses the base addresses passed to it to determine which binding to use.  The following example uses the <protocolMappings> element.

<protocolMapping>
  <add scheme="http"     binding="basicHttpBinding" bindingConfiguration="MyBindingConfiguration"/>
  <add scheme="net.tcp"  binding="netTcpBinding"/>
  <add scheme="net.pipe" binding="netNamedPipeBinding"/>
  <add scheme="net.msmq" binding="netMSMQBinding"/>
</protocolMapping>

Service behaviors are configured for the default endpoints by using anonymous <behavior> sections within <serviceBehaviors> sections.  Any unnamed <behavior> elements within <serviceBehaviors> are used to configure service behaviors.  For example, the following configuration file enables service metadata publishing for all services within the host.

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>    
 </system.serviceModel>

Here is the configuration file from the top of this post modified to use the simplified model.

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
   <bindings>
     <basicHttpBinding>
          <binding maxBufferSize="100"
                   maxReceiveBufferSize="100" />
     </basicHttpBinding>
   </bindings>   
   <protocolMapping>
      <add scheme="http" binding="basicHttpBinding" />
   </protocolMapping>
  </system.serviceModel>