Reading WCF Behaviors from a Configuration File Programmatically When Exposing Self-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 deploy this service programmatically from my desktop application:

I define the host instance:

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

Then I add the anchor endpoint:

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

Now I want to replace the following code with code that reads a behavior named myBehavior from the configuration file, rather than hard-coded behavior parameters.

 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 do not need to do this, you must make sure that the host automatically accepts the configuration from the configuration file and does not give them manually, read this article (Configuring services using configuration files) , this will help you, I placed my service on one line in C # and several of them in the configuration.

This is the second article on (Configuring WCF Services in Code) , my mistake is that I tried to mix two paths!

I will add this as an answer.

+6
source share
3 answers

First you need to open the configuration file 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 behavior:

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

Note that they are of type System.ServiceModel.Configuration.ServiceBehaviorElement , so not exactly what you want.

If you are not opposed to using private APIs, you can call the protected BehaviorExtensionElement.CreateBehavior() method through 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); } 
+7
source

Configuring Services Using Configuration Files

You do not need to do this, you have to make the host automatically accepts the configuration from the configuration file and does not give them manually, read this article (Configuring services using configuration files) , this will help you, I placed my service on one line in C # and several of them in the configuration.

This is the second article on (setting up WCF services in code) , my mistake is that I tried to mix the two paths!

+6
source

Although this is an old question, I had problems finding what I needed elsewhere, so for a 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 very well with web projects, so manually obtaining a section and distinguishing it is easier.

If you really insist on letting System.ServiceModel read the configuration for you, you can 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 second method uses HttpContext.Current , and as we all know, HttpContext.Current is terrible at doing unit tests.

0
source

All Articles