Gotcha
Gotcha

Reputation: 1109

Programmatically define WCF Endpoints with Behaviours

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

Upvotes: 2

Views: 11318

Answers (2)

Gotcha
Gotcha

Reputation: 1109

In the end, I found a simpler way of achieving this - This is one of the method Info I'm accessing:

WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("https://my.service.com/WCFServices/Info.svc"));

binding.Name = "WSHttpBinding_IInfo";
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.Security = new WSHttpSecurity();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport = new HttpTransportSecurity();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message = new NonDualMessageSecurityOverHttp();
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.Security.Message.EstablishSecurityContext = false;

InfoClient proxy = new InfoClient(binding, endpoint);

proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My,                                              X509FindType.FindBySubjectName, "This is my TEST Cert");

object response = proxy.ServiceMethod();

Upvotes: 2

rene
rene

Reputation: 42494

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

Upvotes: 5

Related Questions