Service Configuration Improvements in .NET 4

Hello! I am Amadeo Casas Cuadrado, Program Manager in the Connected Framework team. I would like to introduce some of the new .NET 4 features (available with .NET 4 Beta1!) that we have developed to simplify the user experience when configuring WCF services.

One of the main pain points for Windows Communication Foundation (WCF) users has traditionally been dealing with large configuration files for their services. The WCF configuration schema is complex and provides users with many hard to find features. In .NET 4, we have focused on helping WCF users configure their services. We will be shipping new WCF features in .NET 4 for this reason.

The first feature consists of removing the need for explicit per-service configuration. If you do not configure any <service> elements for your service, and your service does not define programmatically any endpoint, then a set of endpoints will be automatically added to your service, one per service base address and per contract implemented by your service. In each of these endpoints, the endpoint address will correspond to the base address, the binding will be determined by the base address scheme and the contract will be that one implemented by your service.

For instance, the following configuration snippet represents the traditional configuration that a traditional WCF developer would create. Here we see a service that has one base address and implements one contract:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.serviceModel>

<services>

<service name="Service1">

<host>

<baseAddresses>

<add baseAddress="https://localhost:8731/Service1/" />

</baseAddresses>

</host>

<endpoint address=""

binding="basicHttpBinding"

contract="Library1.IService1" />

</service>

</services>

</system.serviceModel>

</configuration>

With .NET 4, the service configuration can be simplified to the following:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

</configuration>

Even better in this case, you could also deploy your service with no configuration file at all!

It is also possible to customize the mapping between base addresses schemes and binding types. For instance, if you need to increase the security of your service and use wsHttpBinding as the default binding for HTTP addresses, the following chunk of configuration will do the trick:

    

<protocolMapping>

  <add scheme="http" binding="wsHttpBinding" />

</protocolMapping>

 

The second feature enables the user to define default values for WCF bindings and behaviors. Those bindings, service behaviors and endpoint behaviors with no name will be applied to your services with no explicit configuration. If we take a look at the configuration generated for a WCF Service Library project in VS2008/.NET 3.5:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <services>

      <service name="Service1"

               behaviorConfiguration="Service1Behavior">

        <host>

          <baseAddresses>

            <add baseAddress="https://localhost:8731/Service1/" />

          </baseAddresses>

        </host>

        <endpoint address=""

                  binding="wsHttpBinding"

                  contract="Library1.IService1" />

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="Service1Behavior">

          <serviceMetadata httpGetEnabled="True" />

          <serviceDebug includeExceptionDetailInFaults="False" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

The new WCF service configuration improvements in .NET 4 allow us to greatly simplify this service configuration to look like this:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceMetadata httpGetEnabled="True" />

          <serviceDebug includeExceptionDetailInFaults="False" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

This is, in fact, exactly how the new VS2010/.NET 4 service configuration template will look like.

The fact that you can define defaults for bindings and behaviors is particularly useful in the WCF configuration inheritance model in .NET 4. Those bindings and behaviors that are defined in upper levels in the configuration hierarchy will be added to your services with no explicit configuration. The following diagram shows an example of how it is possible to simplify your service configuration by relying on configuration elements defined at the machine or the application level:

 

ConfigInheritanceModel

 

In this example, a default basicHttpBinding and a default serviceMetadataBehavior are defined at the machine level. At the next level of the hierarchy, a default serviceDebugBehavior is defined, which will be added to the service, as well as a default endpoint which uses the binding defined at the machine level. As a final note, in .NET 4 Beta 2 all those default service behaviors will be merged and added to the service with no explicit configuration. Stay tuned!

Finally, the third WCF configuration improvement added in .NET 4 is the standard endpoint, which will allow you to define reusable preconfigured endpoints. The main characteristic of these endpoints is that one or more of the address, binding and contract properties have a fixed value. This is particularly useful to define system endpoints that provide their own contract implementation, i.e. not defined by your service, as for instance the MEX endpoint, whose implementation is provided by WCF out of the box. Another interesting feature in the standard endpoints is the possibility of extending the service endpoint with new properties, in a similar way as it is done with the custom bindings. The standard endpoints will also allow you to define custom properties for your service endpoint.

In order to define standard endpoints, you will need to make use of the following properties in your endpoint. The first property is kind, which identifies the standard endpoint type, and must be registered in the <endpointExtensions> section. The second property is endpointConfiguration, which will match the configuration element name of the standard endpoint in the <standardEndpoints> section, used to define the new properties for the endpoint. The last property is isSystemEndpoint, which will flag the endpoint to determine whether it has a fixed contract provided by WCF out of the box or not.

For instance, the following chunk of configuration code defines an udpDiscoveryEndpoint, which has an implicit contract and defines extra properties to the endpoint:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <services>

      <service name="Service1">

        <endpoint address=""

                  binding="basicHttpBinding"

                  contract="Library1.IService1" />

        <endpoint kind="udpDiscoveryEndpoint"

                  endpointConfiguration="udpConfig" />

      </service>

    </services>

    <standardEndpoints>

      <udpDiscoveryEndpoint>

        <standardEndpoint

                  name="udpConfig"

                  multicastAddress="soap.udp://239.255.255.250:3703"

                  ... />

      </udpDiscoveryEndpoint>

    </standardEndpoints>

  </system.serviceModel>

</configuration>

 

The <endpointExtensions> section for the udpDiscoveryEndpoint will be specified in your machine.config:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <extensions>

      <endpointExtensions>

        <add name="udpDiscoveryEndpoint" type="..." />

      </endpointExtensions>

    </extensions>

  </system.serviceModel>

</configuration>

 

What is next?

These features will help you maintain a cleaner configuration model for your WCF services. Let us know what you think!

And this is not the end of it! There are cases in which you will want to have different configuration settings for your services, one for debugging and one for deployment, for instance. In this case, you still need to develop and maintain different web.config files, or to have large chunks of unpleasant commented-out settings. We are currently working on the possibility to define configuration profiles, which will act as bags of different configuration elements that will be imported by the service using that profile. More coming shortly!