简体   繁体   中英

WCF Custom Message Encoder uses Soap1.2 even though I explicitly specify 1.1

I have a custom encoder hooked up to a customBinding that uses a TextMessageEncoding element underwater. I specified specifically that SOAP 1.1 should be used with WS Addressing 1.0. My custom encoder, as I said, uses a text message encoder underwater; the encoder just adds some headers that the service that calls my service wants implemented.

When I add the generated WSDL (that uses SOAP 1.2, even though I specified SOAP 1.1 with WS Addressing 1.0) in SOAPUI and send a request, the content-type is different and it causes an error. I presume this is because WHILE generating the WSDL, it uses Soap 1.2, but WHILE sending a request it tries to use SOAP 1.1 even though a message is send using SOAP 1.2.

There are a few related issues:

  • When I FIRST use <textMessageEncoding messageVersion="Soap11WSAddressing10" writeEncoding="utf-8" /> , add the WSDL to SOAPUI, then change the the encoding to my custom encoder and send a request (Which results in the WSDL being Soap 1.1 so I thought maybe this would be a very hacky workaround) , I get the following error:

    • HTTP/1.1 415 Cannot process the message because the content type 'text/xml;charset=UTF-8' was not the expected type 'text/xml; charset=utf-8'.

      • The issue here is that UTF-8 is in uppercase and that there is whitespace after the ; . I think this is rather weird and should not be an issue!
  • In Visual Studio custom encoder has a squiggly line that says The element 'binding' has invalid child element 'MissingWSAddressingHeadersTextEncoding'. List of possible elements expected: context, .... The element 'binding' has invalid child element 'MissingWSAddressingHeadersTextEncoding'. List of possible elements expected: context, .... I have looked at this Stackoverflow post and used the UI editor, but the squiggly line stays. I have also edited my DotNetConfig.xsd I am 100% confident the address is correct because at run-time the custom encoder works fine.

Please take a look at my code. The links provided in the code are the ones I used to create the encoder.

The class that is used as the extension

namespace DigipoortConnector.Api.Digipoort_Services.Extensions
{
    public class WSAddressingEncodingBindingElementExtension : BindingElementExtensionElement
    {
        public override Type BindingElementType => typeof(WSAddressingEncodingBindingElement);

        protected override BindingElement CreateBindingElement()
        {
            return new WSAddressingEncodingBindingElement();
        }
    }
}

The element, factory and encoder

namespace DigipoortConnector.Api.Digipoort_Services.Extensions
{
//https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.messageencoder(v=vs.110).aspx
//https://blogs.msdn.microsoft.com/carlosfigueira/2011/11/08/wcf-extensibility-message-encoders/

public class WSAddressingEncodingBindingElement : MessageEncodingBindingElement
{
    public override MessageEncoderFactory CreateMessageEncoderFactory() => new WSAddressingEncoderFactory();

    public override MessageVersion MessageVersion
    {
        get => MessageVersion.Soap11WSAddressing10;
        set
        {
            if (value != MessageVersion.Soap11WSAddressing10)
            {
                throw new ArgumentException("Invalid message version");
            }
        }
    }

    public override BindingElement Clone() => new WSAddressingEncodingBindingElement();

    public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
    {
        context.BindingParameters.Add(this);
        return context.BuildInnerChannelFactory<TChannel>();
    }

    public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
    {
        context.BindingParameters.Add(this);
        return context.BuildInnerChannelListener<TChannel>();
    }

    private class WSAddressingEncoderFactory : MessageEncoderFactory
    {
        private MessageEncoder _encoder;

        public override MessageEncoder Encoder
        {
            get
            {
                if (_encoder == null)
                {
                    _encoder = new WSAddressingEncoder();
                }

                return _encoder;
            }
        }

        public override MessageVersion MessageVersion => MessageVersion.Soap11WSAddressing10;
    }

    private class WSAddressingEncoder : MessageEncoder
    {
        private MessageEncoder _underlyingEncoder;
        private const string AddressingNamespace = "http://www.w3.org/2005/08/addressing";

        public WSAddressingEncoder()
        {
            _underlyingEncoder = new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8)
                .CreateMessageEncoderFactory().Encoder;
        }

        public override string ContentType => _underlyingEncoder.ContentType;//.Replace("utf-8", "UTF-8").Replace("; ", ";"); //The replaces are used to fix the uppecase/; problem

        public override string MediaType => _underlyingEncoder.MediaType;

        public override MessageVersion MessageVersion => _underlyingEncoder.MessageVersion;

        public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
            => _underlyingEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType);

        public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
            => _underlyingEncoder.ReadMessage(buffer, bufferManager, contentType);

        public override void WriteMessage(Message message, Stream stream)
            => _underlyingEncoder.WriteMessage(message, stream);

        public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
        {
            message.Headers.Add(MessageHeader.CreateHeader("To", AddressingNamespace, "http://www.w3.org/2005/08/addressing/anonymous"));

            var relatesToHeaderValue = message.Headers.RelatesTo?.ToString();
            message.Headers.Add(MessageHeader.CreateHeader("MessageID", AddressingNamespace, relatesToHeaderValue));

            return _underlyingEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset);
        }
    }
}

}

The binding and the extension element

<customBinding>
      <binding>
        <security
          authenticationMode="CertificateOverTransport"
          messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
          enableUnsecuredResponse="false"
          messageProtectionOrder="EncryptBeforeSign"
          includeTimestamp="true"
          defaultAlgorithmSuite="TripleDesRsa15" />
        <missingWSAddressingHeadersTextEncoding />
        <httpsTransport requireClientCertificate="true" />
      </binding>
</customBinding>

<extensions>
  <bindingElementExtensions>
    <add name="missingWSAddressingHeadersTextEncoding" type="DigipoortConnector.Api.Digipoort_Services.Extensions.WSAddressingEncodingBindingElementExtension, DigipoortConnector.Api"/>
  </bindingElementExtensions>
</extensions>

The only thing I can assume that causes this issue is that at BUILD TIME (When the WSDL will be generated?) my custom encoder is NOT used correctly. But then at run-time it will be used, even though the fallback encoder that was used to generate the WSDL (Textencoder with default SOAP 1.2) is expecting 1.2...?

I have tried using the WCF GUI editor (Right click on web.config and select Edit WCF configuration ). When I open it, it says that the DLL of my custom encoder can't be found. I can go ahead and add it manually, but saving and restarting the editor yields the same result. When inspecting my custom binding and selecting my custom encoder, it shows no results:

缺少信息

Although this could also be because my encoding extension class does not have any other properties..

I am totally at a loss here! Please help me figure this out!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM