【问题标题】:XmlSerializer Deserialize failuresXmlSerializer 反序列化失败
【发布时间】:2010-04-06 22:56:21
【问题描述】:

我有来自第三方服务器的 wsdl。运行 svcutil 并最终获得了一组

XmlNode AMethod(object Request);

方法。有一个单独的 100 页 pdf 描述每个方法的响应/请求对象

我的想法是包装 Web 方法并使用 XmlSerializer 返回强类型对象。返回的 xml 看起来像这样(我删除了肥皂标题):

<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:type="ResponseExt" 
        xmlns="http://www.thirdparty.com/lr/">
  <Code>0</Code>
  <Message>SUCCESS</Message>
  <SessionId>session_token</SessionId>
</Response>

看起来很简单。创建了一个类(来自文档/线路捕获):

[XmlRoot("Response")]
//EDIT added XmlType
[XmlType("ResponseExt", Namespace = "http://www.thirdparty.com/lr/")]
public class MyClass {
    public string Code {get; set;}
    public string Message {get; set;}
    public string SessionId {get; set;}
}

处理时间:

//XmlNode node = xml from above
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlNodeReader reader =  new XmlNodeReader(node);
Myclass myclass = serializer.Deserialize(reader) as MyClass

最后一行是出现内部异常消息的地方:无法识别指定的类型:name='ResponseExt', namespace='http://www.thirdparty.com/lr/', at &lt;Response xmlns=''>。 我不知道如何让 Serializer 开心,以及这两个到底是什么意思

xsi:type="ResponseExt" xmlns="http://www.thirdparty.com/lr/

一如既往地感谢任何建议和指针


编辑:下面接受的答案。

我仍然遇到异常,直到我发现这个,希望它可以节省一些时间。 我开始向后工作。在网络上捕获的 xml。反序列化为我创建的具有正确属性的类:像魅力一样工作。从 web 服务再次尝试 - 异常。由于某种原因,XmlSerializer 无法识别 ResponseExt。

XmlSerializer serializer = new XmlSerializer(typeof(Response));
XmlNode node = (XmlNode)results[0];
XmlDocument doc = new XmlDocument();
doc.LoadXml(node.OuterXml); //reload node
XmlNodeReader reader = new XmlNodeReader(doc.FirstChild); //there is only one node
Response rsp = serializer.Deserialize(reader) as Response; //works

编辑:基础问题 wsdl 文件不完整。在花了 2 天时间并找到了这个(丑陋的)解决方法后,第三方供应商提供了完整 WSDL,其中包含所有反序列化且没有错误的类型。

【问题讨论】:

  • 好的,在你更新问题后我更新了我的答案。

标签: c# xml xmlserializer


【解决方案1】:

当你有 WSDL 时,你为什么要手动反序列化 XML?

如果您有 WSDL,请使用 svcutil.exe 工具或 wsdl.exe 工具为在线发送和接收的 XML 消息生成代理类和 DTO。

Web 服务工具包或“堆栈”的意义在于为您提供这些,这样您就不必手动编写类和 XML 序列化代码。

你试过了吗?您是否尝试通过其中一种工具运行 WSDL?或者您是否尝试在 Visual Studio 中“添加 Web 引用”?


更新问题后,我建议您修改 WSDL,而不是编写自定义代码。您可以为该服务生成一个自定义 WSDL,它将正确生成您想要的代理类。如果您不需要全部 100 种方法(或者有多少方法),那么就把它们排除在外。如果您想要一个方法中的自定义对象,则定义一个对应于该对象的 complexType。这比为每种方法手动编写 XML 反序列化代码更简单、更可靠。


如果你不喜欢这个想法,并且想坚持手动编写 XML 反序列化代码,那么你需要做两件事:

  1. 附加a namespace to the XmlRoot attribute

  2. 将类的名称更改为ResponseExt,并从名为Response 的类派生它。使用 XmlInclude 属性装饰该 Response 类。这与the Xml Serializer with the xsi:type used in the XML fragment 的使用保持一致。

在代码中是这样的:

[XmlRoot("Response", Namespace="http://www.thirdparty.com/lr/")]
public class ResponseExt : Response {
}

[XmlRoot("Response", Namespace="http://www.thirdparty.com/lr/")]
[XmlInclude(typeof(ResponseExt))]
public class Response {
    public string Code {get; set;}
    public string Message {get; set;}
    public string SessionId {get; set;}
}

public class XsiType
{
    public static void Main(string[] args)
    {
        try
        {
            string filename = "XsiType.xml";
            XmlSerializer s1 = new XmlSerializer(typeof(Response));
            ResponseExt r = null;
            using(System.IO.StreamReader reader= System.IO.File.OpenText(filename))
            {
                r= (ResponseExt) s1.Deserialize(reader);
            }

            var builder = new System.Text.StringBuilder();
            var xmlws = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
            using ( var writer = System.Xml.XmlWriter.Create(builder, xmlws))
            {
                //s1.Serialize(writer, r, ns);
                s1.Serialize(writer, r);
            }
            string xml = builder.ToString();
            System.Console.WriteLine(xml);

        }
        catch (System.Exception exc1)
        {
            Console.WriteLine("Exception: {0}", exc1.ToString());
        }
    }
}

相关:How can I force the use of an xsi:type attribute?

【讨论】:

  • Cheeso,我确实运行了工具,不幸的是 wsdl 不包含请求/响应信息,所有方法都采用对象并返回 XmlNode。有一个单独的文档描述每种方法。我更新了问题以澄清问题。
  • 用命名空间更新了代码,重命名了类。还是一样的异常
  • 不知道为什么。如果我是你,我会简化它并将反序列化与消息传输分离。一旦您可以反序列化您认为需要反序列化的类型的消息,使用文件系统文件,然后将该 deser 代码移回 WCF 代理以从 XmlDocument 反序列化。前进的一种方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多