Manage WCF 4.5 Service Configurations from One Location

In an earlier post, I showed how you can configure a WCF 4.5 Web Service in an ASP.NET site with a few lines of code in the beta version of the .NET Framework 4.5; in a later post, I showed how you could configure a WCF 4.5 service both as a TCP-based service and a Web Service in a WCF service library, again using nothing but code (and, again, in the beta). But the beta of WCF 4.5 has another goodie in its pack: The ability to load configurations from a file location of your choice which lets you centralize your service configurations. By default, when a WCF Service or client starts up, it reads configuration information from the application’s config file. Using this new feature, however, you can override that default to specify any file you want

As in with the other code-based configuration features in WCF 4.5, to use this feature you’ll need to add a Shared/static method to your service class called Configure (WCF will call this method before trying to use your service). WCF passes this method a ServiceConfiguration object that has a LoadConfiguration method you can call to load a configuration from any file you want. To use this feature, you’ll also need to make sure that your project has a reference to System.Configuration to pick up some of the classes you’ll need.

The first step in the process is to define an ExeConfigurationFileMap object. This object allows you to specify which files WCF is to look in for your service’s configuration information. There are a number of properties that you can set, including specifying what file to use instead of the machine config file that controls settings for the .NET installation on the computer and the file to use for a WCF client. However, for a WCF service, you want to set the ExeConfigFilename to the path for the file containing your configuration settings. This example points WCF at a file called Service1.config in a folder called configs off the root folder:

Dim cfMap AsNew System.Configuration.
               ExeConfigurationFileMap With
                 { .ExeConfigFilename = "c:configsService1.config"} 

This configuration file must contain your system.serviceModel element enclosed in a <configuration> element, like this:

<configuration> 
  <system.serviceModel> 
  </system.serviceModel> 
</configuration> 

Now that you have your filemap object you can create a configuration object from it. To do this, you call the ConfigurationManager’s OpenMappedExeConfiguration method passing your filemap and a ConfigurationUserLevel of None, as this example does:

cf = System.Configuration.ConfigurationManager. 
       OpenMappedExeConfiguration(cfMap, 
           System.Configuration.ConfigurationUserLevel.None) 

Finally, you pass your configuration object to the ServiceConfiguration parameter using its LoadFromConfiguration method:

sc.LoadFromConfiguration(cf)

There is one wrinkle here: You’re not allowed to have any host elements in the configuration file loaded through the LoadFromConfiguration method (well, you can have host elements in your configuration file but they’ll be ignored). The host element is normally used to set the base address of the service’s endpoints and that’s considered the responsibility of the host rather than the service (for instance, in a WCF service hosted in an ASP.NET site, the site sets the base URL for all services). This is an issue if, in a WCF Service library, you’re using relative addresses for the endPoint elements in your service’s configuration. This example, for instance, specifies that the service’s endpoint is “Service1” added to whatever base address is specified in the host element:


<services> 
  <service name="WCFCentralConfig.Service1"> 
    <endpoint address="Service1" binding="basicHttpBinding" 
                                contract="WCFCentralConfig.IService1"> 

If so, you’ll need to leave a host element in your service library’s config file to specify your base address:

 <system.serviceModel>
  <services>
    <servicename="WCFCentralConfig.Service1">
      <host>
        <baseAddresses>
          <addbaseAddress = "http://localhost:8733/WCFCentralConfig/"/>
        </baseAddresses>
      </host> 
    </service>
  </services>
</system.serviceModel> 

However, if the endpoints in your Service Library specify absolute addresses then you’ll be able to completely delete the system.serviceModel element in your application’s config file. You’ll need to specify the absolute address not only for the endpoint for your service but also, if you’re testing with the WCF Test Client or using the Discover button in the Add Service Reference dialog, for the endpoint used to retrieve the contract for your service (the mex binding) and the httpGetUrl attribute of the serviceMetaData element. You’ll also probably want to specify that, for testing, all the exception detail is to be included in any fault messages you get from your service. Putting it all together, it means that your configuration file will look something like this in a Service Library:

 <configuration> <system.serviceModel>
  <services>
    <service name="WCFCentralConfig.Service1">
      <endpoint
          address="http://localhost:8733/WCFCentralConfig/Service1"
          binding="basicHttpBinding"
          contract="WCFCentralConfig.IService1">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
      <endpoint
         address="http://localhost:8733/WCFCentralConfig/Service1/mex"
         binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"
         httpGetUrl="http://localhost:8733/WCFCentralConfig/Service1/"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>
</configuration> 

Peter Vogel

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.