Reading WCF behavior elements from config file programmticlally when exposing self-hosted service

Sawan picture Sawan · Dec 25, 2012 · Viewed 7.9k times · Source

I have this configuration in my app.config:

    </binding>
  </basicHttpBinding>
</bindings>



<behaviors>
  <serviceBehaviors>
    <behavior name="myBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

I want to expose this service programmatically from my desktop app:

I define the host instance:

ServiceHost host = new ServiceHost(typeof(MyType), new Uri("http://" + hostName + ":" + port + "/MyName"));

Then I add the endpoint with it's binding:

var binding = new BasicHttpBinding("myBinding");
host.AddServiceEndpoint(typeof(IMyInterface), binding, "MyName");

Now, I want to replace the folowing code with some code that reads the behavior named myBehavior from the config file, and not hard-coding the behavior options.

ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpGetEnabled = true };    
host.Description.Behaviors.Add(smb);   
// Enable exeption details
ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;

Then, I can open the host.

host.Open();

* EDIT *

Configuring Services Using Configuration Files

You shouldn't need this way, you should make the host takes its configuration automagically from the config file, and not giving them manually, read this article (Configuring Services Using Configuration Files), it will help you, I have hosted my service in a single line in C# and few ones in config.

This is a second article about (Configuring WCF Services in Code), my fault is that i was trying to mix the two ways!

I will add this as an answer.

Answer

Martin Baulig picture Martin Baulig · Dec 25, 2012

First, you need to open the configuration file by either using

var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

or

var map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "app.config";
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

Then you read the behaviors:

var bindings = BindingsSection.GetSection(config);
var group = ServiceModelSectionGroup.GetSectionGroup(config);
foreach (var behavior in group.Behaviors.ServiceBehaviors)
{
    Console.WriteLine ("BEHAVIOR: {0}", behavior);
}

Note that these are of type System.ServiceModel.Configuration.ServiceBehaviorElement, so not quite what you want yet.

If you don't mind using a private APIs, you can call the protected method BehaviorExtensionElement.CreateBehavior() via reflection:

foreach (BehaviorExtensionElement bxe in behavior)
{
    var createBeh = typeof(BehaviorExtensionElement).GetMethod(
        "CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic);
    IServiceBehavior b = (IServiceBehavior)createBeh.Invoke(bxe, new object[0]);
    Console.WriteLine("BEHAVIOR: {0}", b);
    host.Description.Behaviors.Add (b);
}