3

We have an application that is deployed to many clients, some of which use http others https. When setting up our application the web.config is automatically populated with the WCF endpoints, bindings, etc. We would like to change over the binding to https upon application startup - without modifying the .config file. Is this possible? For example our .config file looks like (this is a snippet):

  <service behaviorConfiguration="Figment.Services.Business.ObjectInfo.ObjectInfoServiceBehavior" name="Figment.Services.Business.ObjectInfo.ObjectInfoService">
    <endpoint address="" binding="basicHttpBinding" bindingNamespace="http://Figment.com/webservices/" contract="Figment.Business.Core.ObjectInfo.IObjectInfoService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

From what I have read it is possible to have an http and https binding at the same time, but we do not want this - if it is https then force it over to use https.

The change should be done in c# on service startup and be permanent while the service is running.

John Hennesey
  • 343
  • 1
  • 2
  • 18
  • Is the application hosting the service, or talking to the service? What do you not want to have two endpoints for the service - http and https? Note that a given service instance cannot have two bindings at the same time - it can only have one. If the service is independent of the applications, I suggest setting up two endpoints and having the individual clients select the proper one. – Tim Feb 17 '17 at 19:13
  • Apologies for not being clearer. This is an application with both a client and a service that talk to each other. When we develop it in house we use http, as we do not have a certificate. Some of our clients have their own certificates and will want it to communicate over https only. I can modify the client app to work https, now it is the server that I do not understand how to modify to never use http, only https. – John Hennesey Feb 17 '17 at 19:15

1 Answers1

0

I know it is an old question, but I have had the same problem and found no answer on the SO. As it took me a couple days of digging to solve the problem, I think it is worth posting it here.

You generally have 3 options here:

1) Configure your service host completely in code (ignoring *.config) as per here

2) Make a script to modify *.config or use other config as per here

3) Use both *.config and programmatic binding configuration

Option (3) is tricky as you have to modify your service host after it has been created but before it would be open (something like host.State == Created). This because modification of bindings of an already open host has no effect. More details here.

To get (3) work you have to use custom host factory. Sample markup:

<%@ ServiceHost 
    Language="C#" 
    Debug="true" 
    CodeBehind="MyService.svc.cs"
    Service="Namespace.MyService, MyService" 
    Factory="Namespace.MyWcfHostFactory, MyService"
%>

MyWcfHostFactory should inherit ServiceHostFactory and extend/override CreateServiceHost method. I am using DI framework (Autofac) which simplifies things a bit. So MyWcfHostFactory just inherits AutofacHostFactory. Startup code (called from either Global.asax Application_Start or static constructor of MyWcfHostFactory):

var builder = new ContainerBuilder();

// Register your service implementations.
builder.RegisterType< Namespace.MyService>();

// Set the dependency resolver.
var container = builder.Build();
AutofacHostFactory.Container = container;
AutofacHostFactory.HostConfigurationAction = (host => PerformHostConfiguration(host));

In PerformHostConfiguration you can overwrite or modify bindings. Code below takes 1st registered endpoint and replaces its binding with https one:

/// <summary> This is used as a delegate to perform wcf host configuration - set Behaviors, global error handlers, auth, etc </summary>
private static void PerformHostConfiguration(ServiceHostBase host) {
    var serviceEndpoint = host.Description.Endpoints.First();
    serviceEndpoint.Binding = new BasicHttpBinding {
        ReaderQuotas = {MaxArrayLength = int.MaxValue},
        MaxBufferSize = int.MaxValue,
        MaxReceivedMessageSize = int.MaxValue,
        Security = new BasicHttpSecurity {
            Mode = BasicHttpSecurityMode.Transport, //main setting for https
        },
    };
}
Anton Krouglov
  • 3,077
  • 2
  • 29
  • 50