Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 791
Sawan Avatar asked Dec 25 '12 18:12

Sawan


People also ask

How to configure WCF service in Web config?

Starting with . NET Framework 4, WCF comes with a new default configuration model that simplifies WCF configuration requirements. If you do not provide any WCF configuration for a particular service, the runtime automatically configures your service with default endpoints, bindings, and behaviors.

What is ServiceModel in web config?

system. serviceModel is a root element of all WCF configuration elements. The configuration information for a service is contained within a system.

What is Servicebehaviors in WCF?

Behavior types are added to the service or service endpoint description objects (on the service or client, respectively) before those objects are used by Windows Communication Foundation (WCF) to create a runtime that executes a WCF service or a WCF client.

Which of the following file contains the code that configures application Behaviour?

A configuration file (web. config) is used to manage various settings that define a website. The settings are stored in XML files that are separate from your application code. In this way you can configure settings independently from your code.


3 Answers

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);
}
like image 124
Martin Baulig Avatar answered Sep 29 '22 10:09

Martin Baulig


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!

like image 23
Sawan Avatar answered Sep 29 '22 11:09

Sawan


While this is an old question, I had problems finding what I needed elsewhere, so for future reference here is my solution.

var behaviorSection = ConfigurationManager.GetSection("system.serviceModel/behaviors") as BehaviorsSection;
if (behaviorSection != null)
{
                // for each behavior, check for client and server certificates
    foreach (EndpointBehaviorElement behavior in behaviorSection.EndpointBehaviors)
    {
        foreach (PropertyInformation pi in behavior.ElementInformation.Properties)
        {
            if (pi.Type == typeof(ClientCredentialsElement))
            {
                var clientCredentials = pi.Value as ClientCredentialsElement;
                var clientCert = clientCredentials.ClientCertificate;
                            // TODO: Add code...
            }
        }
    }
}

ConfigurationManager.Open...Configuration() does not work well with web projects, so manually getting section and casting it is simpler.

If you are really insistent on letting the System.ServiceModel do the config reading for you it is possible to do something like this:

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = System.IO.Path.Combine(HttpContext.Current.Server.MapPath("~"), "web.config"); // the root web.config  
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var group = ServiceModelSectionGroup.GetSectionGroup(config);

foreach (EndpointBehaviorElement item in group.Behaviors.EndpointBehaviors)
{
    // TODO: add code...
}

The 2nd method uses HttpContext.Current, and as we all know HttpContext.Current is horrible when doing unit tests.

like image 44
Tikall Avatar answered Sep 29 '22 10:09

Tikall