XML新手求助:如何将SOAP XML字符串转换为C#对象(WCF场景)
手把手教你把SOAP请求转成C#对象调用WCF服务
别慌!完全不懂XML也没关系,我带你一步步拆解这个SOAP请求,然后转换成C#对象来调用服务。
首先,先看懂这个SOAP请求的结构:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
soapenv:Header/
soapenv:Body
tem:CreateLead
tem:xDoc
John Doe 999999999... ]]>
</tem:xDoc>
</tem:CreateLead>
</soapenv:Body>
</soapenv:Envelope>
这个请求分两层:外层是标准的SOAP信封,内层是CDATA包裹的另一段XML(也就是实际的客户数据)。咱先从内层开始处理。
第一步:定义内层数据的C#类
CDATA里的<CreateLead>节点对应你的业务数据,先给它建个类:
public class CreateLeadData { public string FIRSTNAME { get; set; } public string LASTNAME { get; set; } public string MOBILE { get; set; } // 要是还有其他字段,直接在这里加就行 }
第二步:定义SOAP信封相关的C#类
接下来要把外层的SOAP结构转换成类,注意命名空间必须和请求里的完全一致,不然服务会不认:
using System.Xml; using System.Xml.Serialization; // SOAP信封根节点 [XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", ElementName = "Envelope")] public class SoapEnvelope { [XmlElement(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", ElementName = "Header")] public SoapHeader Header { get; set; } [XmlElement(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", ElementName = "Body")] public SoapBody Body { get; set; } } // SOAP头部(这里没有内容,留空就行) public class SoapHeader { } // SOAP主体 public class SoapBody { [XmlElement(Namespace = "http://tempuri.org/", ElementName = "CreateLead")] public CreateLeadRequest CreateLead { get; set; } } // CreateLead方法的请求参数 public class CreateLeadRequest { [XmlElement(Namespace = "http://tempuri.org/", ElementName = "xDoc")] public XDoc XDoc { get; set; } } // xDoc节点 public class XDoc { [XmlElement(ElementName = "lead")] public Lead Lead { get; set; } } // lead节点,处理CDATA内容 public class Lead { // 实际的XML字符串内容 [XmlIgnore] public string Content { get; set; } // 自动转换成CDATA节点 [XmlElement("lead")] public XmlCDataSection CDataContent { get => new XmlDocument().CreateCDataSection(Content); set => Content = value.Value; } }
第三步:组装对象并序列化成SOAP XML
现在把数据拼起来,转成符合要求的SOAP字符串:
// 1. 构造业务数据 var leadData = new CreateLeadData { FIRSTNAME = "John", LASTNAME = "Doe", MOBILE = "9999999999" }; // 2. 把业务数据序列化成XML字符串(去掉默认的XML声明) var dataSerializer = new XmlSerializer(typeof(CreateLeadData)); using var dataWriter = new StringWriter(); dataSerializer.Serialize(dataWriter, leadData); var leadXml = dataWriter.ToString().Replace(@"<?xml version=""1.0"" encoding=""utf-16""?>", ""); // 3. 组装完整的SOAP信封 var soapEnvelope = new SoapEnvelope { Header = new SoapHeader(), Body = new SoapBody { CreateLead = new CreateLeadRequest { XDoc = new XDoc { Lead = new Lead { Content = leadXml } } } } }; // 4. 把SOAP信封序列化成最终的XML字符串 var soapSerializer = new XmlSerializer(typeof(SoapEnvelope)); using var soapWriter = new StringWriter(); soapSerializer.Serialize(soapWriter, soapEnvelope); var finalSoapXml = soapWriter.ToString();
更简单的方法:直接添加WCF服务引用
要是不想手动写这么多类,Visual Studio能帮你自动生成客户端代码:
- 右键你的C#项目 → 添加 → 服务引用
- 输入WCF服务的地址(比如
http://你的服务地址/Service.svc),点击「转到」 - 给服务起个命名空间(比如
LeadService),点击确定 - 之后直接用生成的客户端调用就行:
// 创建服务客户端 var client = new LeadService.YourServiceClient(); // 构造业务数据并转成XML字符串(步骤和上面一样) var leadData = new CreateLeadData { ... }; var leadXml = ...; // 调用CreateLead方法 var result = client.CreateLead(leadXml);
几个要注意的坑
- 命名空间必须完全匹配:SOAP里的
soapenv和tem对应的URL,一定要和类里的XmlRoot、XmlElement特性里的一致,不然服务会返回错误。 - CDATA里的XML要合法:确保序列化后的业务数据XML没有语法错误,比如标签要闭合。
- 测试先手动验证:可以先用Postman发送这个SOAP请求,确认能正常调用服务,再用C#代码实现,这样更容易排查问题。
内容的提问来源于stack exchange,提问作者Vivek Venugopalan
相关产品推荐
相关产品推荐

