Common User Mistake in .NET 4: Mistyping the WF/WCF Service Configuration Name

Today I am blogging about a common mistake that several developers have committed when using our latest .NET 4 bits. This user experience has its origin in the simplified configuration work developed in this upcoming version of the framework. I will summarize it with the following scenario.

Suppose you would like to write a new WCF Workflow Service Application using Visual Studio 2010. The configuration file that is added to your WF service when using this Visual Studio template makes use of the simplified configuration features in .NET 4, and thus it does not specify any <services> section to define endpoints for your WF service:

<?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>

Therefore, a set of default endpoints will be added to your service.

Now, imagine you would like to take advantage of the new WS-Discovery features and so make your WF service discoverable at runtime. In order to do that, you will need to add a ServiceDiscoveryBehavior and a DiscoveryEndpoint to your WF service. Since the most natural way to do this is via service configuration, you may want to expand the previous configuration to:

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

<configuration>

<system.serviceModel>

< services >

< servicename = "Service"behaviorConfiguration="ServiceBehaviors">

< endpointname = "Endpoint"

address = ""

binding = "basicHttpBinding"

contract = "IService" />

< endpointkind = "udpDiscoveryEndpoint" />

</ service >

</ services >

<behaviors>

<serviceBehaviors>

<behavior name="ServiceBehaviors">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

< serviceDiscovery />

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

</configuration>

The look of this service configuration probably reminds you of what you previously had to write to develop your web services in .NET 3.5 using WCF.

In order to make sure your service is ready to be deployed, you can press CTRL-F5, and then select Service1.xamlx. The following unexpected screen appears:

 

Metadata publishing disabled

 

Why is the metadata publishing currently disabled? Looking at the configuration file, the service we just opened seems to have a ServiceMetadataBehavior with the httpGetEnabled property set to true. Why is this not working properly then?

If you take a closer look at the configuration file, you may realize the following: the default service name in the WCF Workflow Service Application template is Service1, and not Service. After changing the service name in the configuration file to be Service1, and pressing CTRL-F5 again, you will now be able to see the following:

 Metadata publishing enabled

 

The correct configuration has been added to your service!

What we have experienced here is the result of mistyping your service configuration name. When the service was opened, since no explicit configuration was found for it, a default set of endpoints with no default service behaviors was added to your service, and that is why the metadata publishing was not being enabled.

In .NET 3.5, the user experience was an InvalidOperationException thrown when a service was to be open to indicate that it “has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element. ” However, due to the simplified service configuration work in .NET 4, this will not be the case in the upcoming version of the framework, and users will need to make sure that the proper configuration (e.g., security, encoding, etc.) is correctly added to their services.

We are currently thinking on different ways to mitigate this. Adding design time configuration validation seems to be the best solution so far. Opinions?