C# – Programmatically define WCF Endpoints with Behaviours

cwcfweb services

Can anyone show me how to programmatically create WSHttpBindings with Endpoint behaviours?

This is what was generated from WCF Add Service references to 6 WebServices which I manually editted to add behaviours so that all the endpoints uses the same behaviour .

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="epBehaviour">
        <clientCredentials>
          <clientCertificate findValue="This is my TEST Cert" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_IQuote" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_ICommit" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IRetrieve" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IInfo" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IPurge" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_ISearch" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://my.service.com/WCFServices/Info.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInfo" contract="InfoWcfWS.IInfo" name="WSHttpBinding_IInfo" />
    <endpoint address="https://my.service.com/WCFServices/Quote.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IQuote" contract="QuoteWcfWS.IQuote" name="WSHttpBinding_IQuote" />
    <endpoint address="https://my.service.com/WCFServices/Commit.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommit" contract="CommitWcfWS.ICommit" name="WSHttpBinding_ICommit" />
    <endpoint address="https://my.service.com/WCFServices/Retrieve.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IRetrieve" contract="RetrieveWcfWS.IRetrieve" name="WSHttpBinding_IRetrieve" />
    <endpoint address="https://my.service.com/WCFServices/Purge.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IPurge" contract="PurgeWcfWS.IPurge" name="WSHttpBinding_IPurge" />
    <endpoint address="https://my.service.com/WCFServices/Search.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISearch" contract="SearchWcfWS.ISearch" name="WSHttpBinding_ISearch" />
  </client>
</system.serviceModel>

Currently with the generated Proxy from the "Add Service" and adding the behaviour "epBehaviour" which is referenced in the endpoints as a behaviourConfiguration, I can make calls to the endpoints.

Now, my next step is to define the behaviour part and the URL as configurations (May be in the of the web.config) so that I can have different config for Staging and Production.

So my sample Staging config will have the URL defined as below

<appSettings>
  <add key="ServiceUrl.Tls12.Quote" value="https://my.service.com/WCFServices/Quote.svc" />
  <add key="ServiceUrl.Tls12.Commit" value="https://my.service.com/WCFServices/Commit.svc" />
  <add key="ServiceUrl.Tls12.Retrieve" value="https://my.service.com/WCFServices/Retrieve.svc" />
  <add key="ServiceUrl.Tls12.Info" value="https://my.service.com/WCFServices/Info.svc" />
  <add key="ServiceUrl.Tls12.Purge" value="https://my.service.com/WCFServices/Purge.svc" />
  <add key="ServiceUrl.Tls12.Search" value="https://my.service.com/WCFServices/Search.svc" />
</appSettings>

So if I'm consuming the "Info" WebService, my code should be something like

//Code is missing how to define all the specifics like behaviours.
WSHttpBinding binding = new WSHttpBinding();
                EndpointAddress endpoint = new EndpointAddress(new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
             InfoWcfWS.InfoClient proxyNew = new InfoWcfWS.InfoClient(binding, endpoint);

In Summary, given the generated config after an "Add Service", to generate my Proxy Classes, I would like to remove all the config generated by VS and define my own config which will hold the URL; Everything else like endpoints URI, behaviours ..etc should be instantiated programmatically.

Thanks

Best Answer

You have to create instances of the behavior you need either from the System.ServiceModel.Description namespace or create them yourself and then add them to a ChannelFactory.

For your example you create a ChannelFactory for the interface you want and any binding you prefer. You then instantiate a ClientCredentials behavior, configure any of the settings you need on it and add it to the EndPointBehaviors of the ChannelFactory. Then you're ready to create a clientchannel that will give you an object that implements your service interface. You can use that similar as the generated client.

// binding
var binding = new WSHttpBinding();
// using System.ServiceModel
var channelFactory = new ChannelFactory<InfoWcfWS.IInfo>(binding);
// using System.ServiceModel.Description
var endpointClientbehavior = new ClientCredentials();
endpointClientbehavior.ClientCertificate
    .SetCertificate(
    "This is my TEST Cert", 
    StoreLocation.LocalMachine, 
    StoreName.My);
// add the behavior to the endpoint
channelFactory.Endpoint.EndpointBehaviors.Add(endpointClientbehavior);

// done configuring;
channelFactory.Open();
var endpoint = new EndpointAddress(
    new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
// create the clientChannel
var client = channelFactory.CreateChannel(endpoint);
client.Open();
// client implements the operations on InfoWcfWS.IInfo
Related Topic