我有来自第三方服务器的wsdl。跑了svcutil并最终得到了一套
XmlNode AMethod(object Request);
方法。有一个单独的100页pdf描述每个方法的响应/请求对象
我的想法是换行Web方法并使用XmlSerializer返回强类型对象。返回的xml看起来像这样(我删除了soap标题):
<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/',<Response xmlns=''
&gt;。
我无法弄清楚如何让Serializer感到高兴,这两者究竟是什么意思
的xsi:type = “ResponseExt” 的xmlns =“http://www.thirdparty.com/lr/
一如既往地赞赏任何建议和指针
编辑:接受以下答案。
我还是异常,直到我找到了这个,希望它能节省一些时间。 我开始倒退了。在电线上捕获xml。反序列化到我创建的具有正确属性的类:像魅力一样工作。再次尝试从webservice - 例外。由于某种原因,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文件未完成。在花了两天时间找到这个(丑陋的)解决方法之后,第三方供应商提供了完整 WSDL,其中所有类型都反序列化而没有错误。
答案 0 :(得分:1)
为什么在使用WSDL时手动反序列化XML?
如果您有WSDL,请使用svcutil.exe工具或wsdl.exe工具为线路上发送和接收的XML消息生成代理类和DTO。
Web服务工具包或“堆栈”的目的是为您提供此功能,这样您就不必手动编写类和XML序列化代码。
你尝试过这个吗?您是否尝试通过其中一种工具运行WSDL?或者您是否尝试在Visual Studio中“添加Web引用”?更新问题后,我建议您修改WSDL,而不是编写自定义代码。您可以为服务生成自定义WSDL,这将正确生成所需的代理类。如果您不需要所有100种方法(或者有多种方法),请将它们排除在外。如果需要方法中的自定义对象,请定义与该对象对应的complexType。这比为每种方法手动编写XML反序列化代码更简单,更可靠。
如果您不喜欢这个想法,并希望坚持手动编写XML反序列化代码,那么您需要做两件事:
将您的班级名称更改为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());
}
}
}