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

.NET 6中忽略SOAP信封与Body反序列化XML至C#对象报错求助

解决SOAP XML反序列化时忽略<S:Envelope>和<S:Body>的问题

问题场景

现有如下SOAP格式XML:

<S:Envelope
    xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ValidationResponse>
            <Context>
                <MainInformation>
                    <ServiceID>10</ServiceID>
                    <TransactionDate>2015-07-29T09:06:05.694+02:00</TransactionDate>
                </MainInformation>
            </Context>
            <PlayerStatus>
                <PlayerCPRStatus>CPRIsRegistered</PlayerCPRStatus>
                <PlayerAge>AgeIs18OrAbove</PlayerAge>
                <ExclusionStatus>PersonIsNotRegistered</ExclusionStatus>
            </PlayerStatus>
        </ValidationResponse>
    </S:Body>
</S:Envelope>

需要忽略<S:Envelope>和<S:Body>元素,将内部的<ValidationResponse>反序列化为C#对象,但执行代码时抛出异常:InvalidOperationException: envelope was not expected。

原尝试代码(存在问题):

public class Resposnse // 类名拼写错误,属性映射完全不匹配XML结构
{
    [XmlElement("Age")]
    public string Age { get; set; }

    [XmlElement("PlayerStatus")]
    public string CPRStatus { get; set; }

    [XmlElement("ExclusionStatus")]
    public string ExclusionStatus { get; set; }
}

string xml = "mentioned xml in example";
var serializer = new XmlSerializer(typeof(Resposnse));

Resposnse xmlResponse;

using (TextReader reader = new StringReader(xml))
{
    xmlResponse = (Resposnse)serializer.Deserialize(reader);
}

问题原因

  1. 根节点不匹配:XmlSerializer默认以XML的根节点(<S:Envelope>)作为反序列化目标,但你的类对应的是内部的<ValidationResponse>节点,直接反序列化整个XML会导致节点不匹配报错。
  2. 类结构与XML不对应:原类的属性名称、XmlElement标签完全和XML中的节点(如PlayerCPRStatus、PlayerAge)不匹配,类名还存在拼写错误(Resposnse应为Response)。

解决方法

方法一:先定位到<ValidationResponse>节点再反序列化

先通过XmlDocument加载XML,找到目标节点后再进行反序列化:

步骤1:定义匹配XML结构的类

// 对应ValidationResponse节点
public class ValidationResponse
{
    public Context Context { get; set; }
    public PlayerStatus PlayerStatus { get; set; }
}

// 对应Context节点
public class Context
{
    public MainInformation MainInformation { get; set; }
}

// 对应MainInformation节点
public class MainInformation
{
    public int ServiceID { get; set; }
    public DateTime TransactionDate { get; set; }
}

// 对应PlayerStatus节点
public class PlayerStatus
{
    public string PlayerCPRStatus { get; set; }
    public string PlayerAge { get; set; }
    public string ExclusionStatus { get; set; }
}

步骤2:定位目标节点并反序列化

string xml = "你的SOAP XML字符串";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

// 找到ValidationResponse节点
XmlNode targetNode = doc.SelectSingleNode("//ValidationResponse");

var serializer = new XmlSerializer(typeof(ValidationResponse));
ValidationResponse response;

using (XmlNodeReader reader = new XmlNodeReader(targetNode))
{
    response = (ValidationResponse)serializer.Deserialize(reader);
}

// 可正常访问response.PlayerStatus.PlayerCPRStatus等属性

方法二:使用XmlReader跳过Envelope和Body节点

通过XmlReader直接定位到目标节点,避免加载整个XmlDocument:

string xml = "你的SOAP XML字符串";
ValidationResponse response = null;

using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
{
    // 跳过Envelope节点
    reader.ReadToFollowing("Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
    // 跳过Body节点
    reader.ReadToFollowing("Body", "http://schemas.xmlsoap.org/soap/envelope/");
    // 定位到ValidationResponse节点
    reader.ReadToFollowing("ValidationResponse");

    var serializer = new XmlSerializer(typeof(ValidationResponse));
    response = (ValidationResponse)serializer.Deserialize(reader);
}

注意事项

  • 确保类的结构和XML节点完全对应,属性名称默认会匹配相同名称的XML节点,无需额外标注XmlElement(除非名称不一致)。
  • 如果XML节点有命名空间,需要在类上添加[XmlRoot]或[XmlElement]指定命名空间,本示例中<ValidationResponse>无命名空间,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:37:07