.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); }
问题原因
- 根节点不匹配:XmlSerializer默认以XML的根节点(
<S:Envelope>)作为反序列化目标,但你的类对应的是内部的<ValidationResponse>节点,直接反序列化整个XML会导致节点不匹配报错。 - 类结构与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
相关产品推荐
相关产品推荐

