即使我明确指定1.1,WCF自定义消息编码器也使用Soap1.2

时间:2018-06-15 12:57:13

标签: c# asp.net wcf soap wsdl

我有一个自定义编码器连接到customBinding水下使用TextMessageEncoding元素。我明确指出SOAP 1.1应该与WS Addressing 1.0一起使用。正如我所说,我的自定义编码器在水下使用文本消息编码器;编码器只是添加了一些调用我的服务的服务实现的标头。

当我在SOAPUI中添加生成的WSDL(使用SOAP 1.2,即使我在WS Addressing 1.0中指定了SOAP 1.1)并发送请求时,内容类型也不同,从而导致错误。我认为这是因为WHILE生成WSDL,它使用Soap 1.2,但WHILE发送请求它尝试使用SOAP 1.1,即使使用SOAP 1.2发送消息。

有一些相关问题:

  • 当我第一次使用<textMessageEncoding messageVersion="Soap11WSAddressing10" writeEncoding="utf-8" />时,将WSDL添加到SOAPUI,然后将编码更改为我的自定义编码器并发送请求(这导致WSDL成为Soap 1.1所以我想也许这会是一个非常hacky解决方法),我收到以下错误:

    • 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'.

      • 这里的问题是UTF-8是大写的,;后面有空格。我觉得这很奇怪,应该不是问题!
  • 在Visual Studio中,自定义编码器有一条波浪线,表示The element 'binding' has invalid child element 'MissingWSAddressingHeadersTextEncoding'. List of possible elements expected: context, ....我查看了this Stackoverflow post并使用了UI编辑器,但是波浪线仍然存在。我还编辑了我的DotNetConfig.xsd我100%确信地址是正确的,因为在运行时自定义编码器工作正常。

请查看我的代码。代码中提供的链接是我用来创建编码器的链接。

用作扩展名

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

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

元素,工厂和编码器

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);
        }
    }
}

}

绑定和扩展元素

<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>

我唯一可以假设导致此问题的是在BUILD TIME(当生成WSDL时?)我的自定义编码器未正确使用。但是在运行时它会被使用,即使用于生成WSDL(具有默认SOAP 1.2的Textencoder)的回退编码器期望1.2 ......?

我尝试过使用WCF GUI编辑器(右键单击web.config并选择Edit WCF configuration)。当我打开它时,它说我的自定义编码器的DLL无法找到。我可以继续手动添加它,但保存并重新启动编辑器会产生相同的结果。检查我的自定义绑定并选择我的自定义编码器时,它没有显示任何结果:

Missing info

虽然这也可能是因为我的编码扩展类没有任何其他属性..

我在这里完全不知所措!请帮我解决这个问题!