WCF - how to create programatically custom binding

2019-03-20 19:24发布

问题:

I'd like to convert my current HTTP/HTTPS WCF binding settings to use binary message encoding and I need to do it in code - not in XML configuration. AFAIK it's necessary to create CustomBinding object and set proper BindingElements, but I'm not able to figure out what elements should I use in my scenario.

Main points in my WCF configuration are:

  • use HTTP or HTTPS transport depending on configuration (in app.config)
  • use username message security
  • todo: add binary encoding instead of default text

My current code for setting the binding up (working, but without the binary encoding):

var isHttps = Settings.Default.wcfServiceBaseAddress.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase);
var binding = new WSHttpBinding(isHttps ? SecurityMode.TransportWithMessageCredential : SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

I was trying this code, but it doesn't work - I don't know how to set message security element for username message security:

var custBinding = new CustomBinding();
custBinding.Elements.Add(new BinaryMessageEncodingBindingElement());
//Transport Security (Not Required)
if (isHttps)
{
    custBinding.Elements.Add(SecurityBindingElement.CreateUserNameForSslBindingElement());
}
//Transport (Required)
custBinding.Elements.Add(isHttps ?
    new HttpsTransportBindingElement() :
    new HttpTransportBindingElement());

Anybody knows how to set this up? I tried to search for similar problem/solution, but didn't succeeded...

回答1:

I almost forgot this question, but here is my custom binding class which works with binary binding over HTTP with username+password validation and also allows to turn GZip compression on...

    public class CustomHttpBinding: CustomBinding
{
    private readonly bool useHttps;
    private readonly bool useBinaryEncoding;
    private readonly bool useCompression;
    private readonly HttpTransportBindingElement transport;

    public CustomHttpBinding(bool useHttps, bool binaryEncoding = true, bool compressMessages = false)
    {
        this.useHttps = useHttps;
        transport = useHttps ? new HttpsTransportBindingElement() : new HttpTransportBindingElement();
        useBinaryEncoding = binaryEncoding;
        useCompression = compressMessages;
    }

    public long MaxMessageSize{set
    {
        transport.MaxReceivedMessageSize = value;
        transport.MaxBufferSize = (int) value;
    }}

    public override BindingElementCollection CreateBindingElements()
    {
        BindingElement security;
        if (useHttps)
        {
            security = SecurityBindingElement.CreateSecureConversationBindingElement(
                SecurityBindingElement.CreateUserNameOverTransportBindingElement());
        }
        else
        {
            security = SecurityBindingElement.CreateSecureConversationBindingElement(
                SecurityBindingElement.CreateUserNameForSslBindingElement(true));
        }

        MessageEncodingBindingElement encoding;
        if (useCompression)
        {
            encoding = new GZipMessageEncodingBindingElement(useBinaryEncoding
                                                                ? (MessageEncodingBindingElement)
                                                                  new BinaryMessageEncodingBindingElement()
                                                                : new TextMessageEncodingBindingElement());
        }
        else
        {
            encoding = useBinaryEncoding
                        ? (MessageEncodingBindingElement) new BinaryMessageEncodingBindingElement()
                        : new TextMessageEncodingBindingElement();
        }

        return new BindingElementCollection(new[]
            {
                security,
                encoding,
                transport,
            });
    }
}


回答2:

Try SecurityBindingElement.CreateUserNameOverTransportBindingElement() instead:

var custBinding = new CustomBinding();
custBinding.Elements.Add(new BinaryMessageEncodingBindingElement());
//Transport Security (Not Required)
if (isHttps)
{
  custBinding.Elements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());
}
//Transport (Required)
custBinding.Elements.Add(isHttps ?
   new HttpsTransportBindingElement() :
   new HttpTransportBindingElement());


回答3:

The SecurityBindingElement has a AllowInsecureTransport property. If you set this to true you can use the HttpTransportBindingElement with message user name and password security.