.NET5使用WCF调用SOAP服务如何仅修改响应支持的Content-Type
解决方案
针对你遇到的WCF客户端请求/响应要求不同Content-Type的问题,最优方案是实现仅修改响应Content-Type识别逻辑的自定义消息编码器,完全不需要改动请求发送逻辑,也不用更换框架重写代码。
实现步骤
1. 自定义消息编码器
该编码器会在写入请求时保留默认的text/xml类型,仅在读取响应时兼容application/xml类型:
// 自定义消息编码器 public class CustomTextMessageEncoder : MessageEncoder { private readonly MessageEncoder _defaultEncoder; public CustomTextMessageEncoder(MessageEncoder defaultEncoder) { _defaultEncoder = defaultEncoder; } // 请求发出时固定用text/xml,符合服务端要求 public override string ContentType => "text/xml"; public override string MediaType => "text/xml"; public override MessageVersion MessageVersion => _defaultEncoder.MessageVersion; // 处理响应时自动兼容application/xml public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType) { if (contentType.Equals("application/xml", StringComparison.OrdinalIgnoreCase)) contentType = "text/xml"; return _defaultEncoder.ReadMessage(buffer, bufferManager, contentType); } public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) { if (contentType.Equals("application/xml", StringComparison.OrdinalIgnoreCase)) contentType = "text/xml"; return _defaultEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType); } // 写入请求完全复用默认逻辑,保证Content-Type符合要求 public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) { return _defaultEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset); } public override void WriteMessage(Message message, Stream stream) { _defaultEncoder.WriteMessage(message, stream); } } // 编码器工厂 public class CustomTextMessageEncoderFactory : MessageEncoderFactory { private readonly CustomTextMessageEncoder _encoder; public CustomTextMessageEncoderFactory(MessageEncoderFactory defaultFactory) { _encoder = new CustomTextMessageEncoder(defaultFactory.Encoder); } public override MessageEncoder Encoder => _encoder; public override MessageVersion MessageVersion => _encoder.MessageVersion; } // 自定义绑定元素,用于替换默认编码逻辑 public class CustomTextMessageBindingElement : MessageEncodingBindingElement { private readonly TextMessageEncodingBindingElement _defaultEncodingElement; public CustomTextMessageBindingElement(TextMessageEncodingBindingElement defaultElement) { _defaultEncodingElement = defaultElement; } public override MessageEncoderFactory CreateMessageEncoderFactory() { return new CustomTextMessageEncoderFactory(_defaultEncodingElement.CreateMessageEncoderFactory()); } public override MessageVersion MessageVersion { get => _defaultEncodingElement.MessageVersion; set => _defaultEncodingElement.MessageVersion = value; } public override BindingElement Clone() { return new CustomTextMessageBindingElement((TextMessageEncodingBindingElement)_defaultEncodingElement.Clone()); } }
2. 替换原有绑定配置
不需要修改你原有业务调用逻辑,仅需要把默认的BasicHttpBinding替换为添加了自定义编码元素的自定义绑定即可:
// 复用原有BasicHttpBinding的所有配置,仅替换编码逻辑 var defaultBinding = new BasicHttpBinding(); var customBinding = new CustomBinding(defaultBinding); // 替换默认的文本编码元素 var defaultEncodingElement = customBinding.Elements.Find<TextMessageEncodingBindingElement>(); customBinding.Elements.Remove(defaultEncodingElement); customBinding.Elements.Insert(0, new CustomTextMessageBindingElement(defaultEncodingElement)); // 后续调用逻辑和你原来的代码完全一致 var endpoint = new EndpointAddress("http://[...]/inquiry"); var channelFactory = new ChannelFactory<InquiryServiceSoapPort>(customBinding, endpoint); var serviceClient = channelFactory.CreateChannel(); var inquiry = new Inquiry(); var result = serviceClient.createInquiry(inquiry);
方案说明
- 完全是客户端侧修改,不需要服务端做任何调整
- 请求发出的Content-Type仍然是服务端要求的
text/xml,不会被服务端拒绝 - 仅在响应处理阶段将
application/xml转换为WCF默认支持的text/xml,不影响任何业务逻辑解析 - 不需要重写整个调用逻辑,仅需要调整绑定配置即可
内容的提问来源于stack exchange,提问作者thorstenmz
相关产品推荐
相关产品推荐

