C# XmlSerializer和xsi:反序列化
由于xsi:type=“p:OUTPUT-HEADER”属性,我很难尝试反序列化与WCF SOAP服务错误详细信息部分相对应的这段XML代码:C# XmlSerializer和xsi:反序列化,c#,wcf,xmlserializer,C#,Wcf,Xmlserializer,由于xsi:type=“p:OUTPUT-HEADER”属性,我很难尝试反序列化与WCF SOAP服务错误详细信息部分相对应的这段XML代码: <p:OUTPUT-HEADER xsi:type="p:OUTPUT-HEADER" xmlns:p="http://aaa.bbb.ccc/v2" xmlns:ns0="http://aaa.bbb.ccc/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <F
<p:OUTPUT-HEADER xsi:type="p:OUTPUT-HEADER" xmlns:p="http://aaa.bbb.ccc/v2" xmlns:ns0="http://aaa.bbb.ccc/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FAULT>
<p:COD-ERROR>2951</p:COD-ERROR>
<p:COD-SEV>8</p:COD-SEV>
<p:MSG-ERROR>Error message</p:MSG-ERROR>
</FAULT>
<CNL-OUT>xxx</CNL-OUT>
</p:OUTPUT-HEADER>
XmlSerializer:
XmlSerializer x = new XmlSerializer(typeof(OutputHeader));
调用反序列化方法时出现的错误:
“无法识别指定的类型:名称
='OUTPUT-HEADER',命名空间='',位于。“
是否可以修饰类以正确地反序列化此XML?
非常感谢您的任何想法,谢谢 而不是
XmlSerializer
,似乎必须使用来反序列化此XML。此序列化程序是唯一的,因此您只需删除指定使用XmlSerializer
的代码即可
按如下方式设计您的类型:
[DataContract(Namespace = "")]
public abstract class OutputHeaderBase
{
[DataMember(Name = "FAULT", Order = 1)]
public Fault FaultSection { get; set; }
[DataMember(Name = "CNL-OUT", Order = 2)]
public string ClnOut { get; set; }
}
[DataContract(Name = "OUTPUT-HEADER", Namespace = "http://aaa.bbb.ccc/v2")]
public class OutputHeader : OutputHeaderBase
{
}
[DataContract(Name = "FAULT", Namespace = "http://aaa.bbb.ccc/v2")]
public class Fault
{
[DataMember(Name = "COD-ERROR", Order = 1)]
public int CodigoError { get; set; }
[DataMember(Name = "COD-SEV", Order = 2)]
public int Severidad { get; set; }
[DataMember(Name = "MSG-ERROR", Order = 3)]
public string Mensaje { get; set; }
}
[XmlRoot(ElementName = "OUTPUT-HEADER", Namespace = "http://aaa.bbb.ccc/v2")]
[XmlInclude(typeof(OutputHeaderSubclass))] // Artificial subtype to trigger handling of the `xsi:type` attribute.
[XmlInclude(typeof(OutputHeader))]
public class OutputHeader
{
[XmlElement(ElementName = "FAULT", Namespace = "")]
public Fault FaultSection { get; set; }
[XmlElement(ElementName = "CNL-OUT", Namespace = "")]
public string ClnOut { get; set; }
}
[XmlRoot(ElementName = "OUTPUT-HEADER-SUBCLASS", Namespace = "http://aaa.bbb.ccc/v2")]
public class OutputHeaderSubclass : OutputHeader
{
}
然后将您的操作契约声明为返回(或接受)类型为OutputHeader
(不是OutputHeaderBase
)的对象
最后,通过从服务和/或操作契约中删除来切换回数据契约序列化,您应该已经准备好了。有关切换的详细信息,请参阅
(另请注意,Fault
的属性需要放在正确的命名空间中。)
为什么这样做
该属性是w3c标准属性,允许元素显式声明其类型。在序列化多态类型时,使用和属性传递实际的类型信息。然而,以下要素:
<p:OUTPUT-HEADER
xsi:type="p:OUTPUT-HEADER"
xmlns:p="http://aaa.bbb.ccc/v2"
xmlns:ns0="http://aaa.bbb.ccc/v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
</p:OUTPUT-HEADER>
然后反序列化到
outputhreader
可能会很好地工作。不幸的是,事实并非如此XmlSerializer
为冗余属性引发异常,而不是处理它。相反地,DataContractSerializer
没有,所以这是要使用的。WCF自动序列化和反序列化通过网络发送的内容。是否有特定的原因需要手动执行此操作?我知道“自动”方式应该是使用FaultException.GetDetail,但是没有生成OutputHeader类,因为wsdl不包含任何与此相关的信息。因此,我的下一步是获取FaultException.getReaderAttailContents()流并尝试对其进行反序列化。还是我在这里遗漏了什么?谢谢令人印象深刻,解释和记录都很好。我使用XmlSerializer是因为我认为DataContractSerializer无法处理层次结构中的不同名称空间,但现在我明白了,我误解了XML。非常感谢dbc!
[XmlRoot(ElementName = "OUTPUT-HEADER", Namespace = "http://aaa.bbb.ccc/v2")]
[XmlInclude(typeof(OutputHeaderSubclass))] // Artificial subtype to trigger handling of the `xsi:type` attribute.
[XmlInclude(typeof(OutputHeader))]
public class OutputHeader
{
[XmlElement(ElementName = "FAULT", Namespace = "")]
public Fault FaultSection { get; set; }
[XmlElement(ElementName = "CNL-OUT", Namespace = "")]
public string ClnOut { get; set; }
}
[XmlRoot(ElementName = "OUTPUT-HEADER-SUBCLASS", Namespace = "http://aaa.bbb.ccc/v2")]
public class OutputHeaderSubclass : OutputHeader
{
}