Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing WCF Service reference URL based on environment

I have a web application that uses a number of WCF Services. I deploy my web application in various environments (dev, UAT, production etc). The URL of each WCF Service is different for each environment. I am using .NET 3.5 andbasicHttpBindings

The web application uses a framework to support machine-specific settings in my web.config file. When instantiating an instance of a WCF Service client I call a function that creates the instance of the WCF Service client using the constructor overload that takes the arguments:

System.ServiceModel.Channels.Binding binding,
System.ServiceModel.EndpointAddress remoteAddress

In essence the <system.serviceModel><bindings><basicHttpBinding><binding> configuration in web.config has been replicated in C# code.

This approach works well.

However, I now have to enhance this approach to work with a WCF service that uses an X509 certificate. This means that I have to replicate the following additional settings in web.config in C# code:

<!-- inside the binding section -->
<security mode="Message">
  <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
  <message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>


<behaviors>
  <endpointBehaviors>
    <behavior name="MyServiceBehaviour">
      <clientCredentials>
        <clientCertificate storeLocation="LocalMachine" storeName="My"
          x509FindType="FindByThumbprint" findValue="1234abcd" />
        <serviceCertificate>
          <defaultCertificate storeLocation="LocalMachine" storeName="My"
            x509FindType="FindByThumbprint" findValue="5678efgh" />
          <authentication trustedStoreLocation="LocalMachine"
            certificateValidationMode="None" />
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>

I am having some difficulty figuring out how to code this configuration in C#.

Two questions

  • Can anyone recommend a better approach for managing WCF Service reference URLs across multiple environments?
  • Alternatively, any suggestions on how to replicate the above web.config section in C# will be welcomed
like image 919
Richard Ev Avatar asked Apr 28 '09 12:04

Richard Ev


People also ask

How do I change my WCF service reference?

In Solution Explorer, right-click the name of the project to which you want to add the service, and then click Add Service Reference. The Add Service Reference dialog box appears. Click Discover. All services (both WCF Data Services and WCF services) in the current solution are added to the Services list.

How do I change the service reference URL in C#?

No need to write any code. Just change the URL in app. config and it will work.

How do I add a WCF service reference in a net core 3.1 application?

NET Standard project, this option is available when you right-click on the Dependencies node of the project in Solution Explorer and choose Manage Connected Services.) On the Connected Services page, select Add Service Reference. The Add service reference page opens. Select WCF Web Service, and then choose Next.


2 Answers

One possible approach would be to "externalize" certain parts of your <system.serviceModel> configuration into external files, one per environment.

E.g. we have "bindings.dev.config" and "bindings.test.config", which we then reference in our main web.config like this:

<system.serviceModel>
  <bindings configSource="bindings.dev.config" />
</system.serviceModel>

That way, all you need to change from DEV to PROD is this one line of config XML.

Basically, in .NET 2.0 config, any configuration element can be "externalized". You cannot however externalize configGroups (such as "system.serviceModel") directly - you have to be on the "configuration element" level.

Marc

EDIT: OK, so NO config edit changes to switch between environments..... In that case, you probably have to dream up a naming scheme, e.g. name your bindings, behaviors and endpoints in such a way, that you can distinguish them at runtime.

Something like:

<bindings>
  <binding name="Default_DEV">
    .....
  </binding>
  <binding name="Default_PROD">
    .....
  </binding>
</bindings>

that way, you could build up the name of the element you want (e.g. binding "Default_PROD") from your code and the environment you're running in, and then grab the according config from the config file which contains all the config settings for all environments.

like image 111
marc_s Avatar answered Sep 19 '22 02:09

marc_s


The following code replicates the configuration in my original question:

myClient.ClientCredentials.ClientCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindByThumbprint,
    "1234abcd");

myClient.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindByThumbprint,
    "5678efgh");

myClient.ClientCredentials.ServiceCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
myClient.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

In the production code the two thumbprint values are stored in appSettings in the web.config file.

like image 45
Richard Ev Avatar answered Sep 21 '22 02:09

Richard Ev