You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WCF序列化器不对SOAP Body内容编码,保留CDATA格式?

解决WCF序列化器不对SOAP Body中CDATA内容编码的问题

你不需要退回字符串模板方式,WCF提供了自定义序列化的能力,可以精准控制CDATA内容的输出,避免特殊字符被编码。以下是两种可行的解决方案:

方案1:扩展生成的WORKRequest类实现IXmlSerializable

利用生成类的partial特性,添加自定义序列化逻辑,手动将data字段包裹为CDATA节点,绕开默认的编码行为。

实现代码

在同一个命名空间下新建一个代码文件,扩展WORKRequest类:

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

public partial class WORKRequest : IXmlSerializable
{
    XmlSchema IXmlSerializable.GetSchema() => null;

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        // 客户端若无需反序列化请求,可简化实现
        reader.ReadStartElement("WORK");
        if (reader.Name == "data")
        {
            reader.ReadStartElement();
            data = reader.NodeType == XmlNodeType.CDATA ? reader.Value : reader.ReadContentAsString();
            reader.Read();
            reader.ReadEndElement();
        }
        reader.ReadEndElement();
    }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        // 手动写入data节点并包裹CDATA,避免特殊字符编码
        writer.WriteStartElement("data");
        writer.WriteCData(data);
        writer.WriteEndElement();
    }
}

使用方式

保持原有调用逻辑不变,直接传入包含XML的字符串即可:

var request = new WORKRequest("<root><item>123</item></root>");
var response = client.WORK(request);

此时SOAP Body中的data节点会被序列化为:

<data><![CDATA[<root><item>123</item></root>]]></data>

方案2:手动构造SOAP消息(完全绕过自动序列化)

如果自定义序列化仍有兼容性问题,可以直接构造完整的SOAP信封,完全控制请求内容。

实现代码

using (var factory = new ChannelFactory<ANDR_servicePort>("ANDR_servicePort"))
{
    var channel = factory.CreateChannel();
    var cdataContent = "<root><item>123</item></root>";
    
    // 手动构造符合要求的SOAP信封
    var soapEnvelope = $@"<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
        <s:Body>
            <WORK xmlns=""http://soapEndpoint"">
                <data><![CDATA[{cdataContent}]]></data>
            </WORK>
        </s:Body>
    </s:Envelope>";

    using (var stringReader = new StringReader(soapEnvelope))
    using (var xmlReader = XmlReader.Create(stringReader))
    {
        var message = Message.CreateMessage(xmlReader, int.MaxValue, MessageVersion.Soap11);
        var reply = ((IRequestChannel)channel).Request(message);

        // 反序列化回复得到WORKResponse
        var serializer = new XmlSerializer(typeof(WORKResponse));
        using (var replyReader = reply.GetReaderAtBodyContents())
        {
            var response = (WORKResponse)serializer.Deserialize(replyReader);
            // 处理返回结果
        }
    }
}

为什么你之前的尝试没成功?

  • IClientMessageInspector时机不对:BeforeSendRequest触发时消息尚未完成序列化,看不到编码后的字符;而WCF消息默认只读,无法在序列化后直接修改内容。
  • XElement类型不兼容:你的契约使用Rpc/Encoded风格,XmlSerializer无法直接将XElement序列化为Encoded格式的SOAP节点,因此抛出异常。

内容的提问来源于stack exchange,提问作者AlinF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:32:46