为什么.NET不会从Web服务反序列化我的原始数组?

救命! 我有一个由C#应用程序使用的Axis Web服务。 一切都很好,除了长值数组总是遇到[0,0,0,0] – 正确的长度,但值不反序列化。 我尝试过其他原语(整数,双打),同样的事情发生了。 我该怎么办? 我不想改变我的服务的语义。

这就是我最终的结果。 我从来没有找到另一个解决方案,所以如果你有更好的东西,无论如何,贡献。

首先,wsdl:types区域中的长数组定义:

       

接下来,我们创建一个SoapExtensionAttribute来执行修复。 似乎问题是.NET没有跟随包含double值的元素的multiref id。 因此,我们处理数组项,找到值,然后将值插入元素:

 [AttributeUsage(AttributeTargets.Method)] public class LongArrayHelperAttribute : SoapExtensionAttribute { private int priority = 0; public override Type ExtensionType { get { return typeof (LongArrayHelper); } } public override int Priority { get { return priority; } set { priority = value; } } } public class LongArrayHelper : SoapExtension { private static ILog log = LogManager.GetLogger(typeof (LongArrayHelper)); public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) { return null; } public override object GetInitializer(Type serviceType) { return null; } public override void Initialize(object initializer) { } private Stream originalStream; private Stream newStream; public override void ProcessMessage(SoapMessage m) { switch (m.Stage) { case SoapMessageStage.AfterSerialize: newStream.Position = 0; //need to reset stream CopyStream(newStream, originalStream); break; case SoapMessageStage.BeforeDeserialize: XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = false; settings.NewLineOnAttributes = false; settings.NewLineHandling = NewLineHandling.None; settings.NewLineChars = ""; XmlWriter writer = XmlWriter.Create(newStream, settings); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(originalStream); List longArrayItems = new List(); Dictionary multiRefs = new Dictionary(); FindImportantNodes(xmlDocument.DocumentElement, longArrayItems, multiRefs); FixLongArrays(longArrayItems, multiRefs); xmlDocument.Save(writer); newStream.Position = 0; break; } } private static void FindImportantNodes(XmlElement element, List longArrayItems, Dictionary multiRefs) { string val = element.GetAttribute("soapenc:arrayType"); if (val != null && val.Contains(":long[")) { longArrayItems.Add(element); } if (element.Name == "multiRef") { multiRefs[element.GetAttribute("id")] = element; } foreach (XmlNode node in element.ChildNodes) { XmlElement child = node as XmlElement; if (child != null) { FindImportantNodes(child, longArrayItems, multiRefs); } } } private static void FixLongArrays(List longArrayItems, Dictionary multiRefs) { foreach (XmlElement element in longArrayItems) { foreach (XmlNode node in element.ChildNodes) { XmlElement child = node as XmlElement; if (child != null) { string href = child.GetAttribute("href"); if (href == null || href.Length == 0) { continue; } if (href.StartsWith("#")) { href = href.Remove(0, 1); } XmlElement multiRef = multiRefs[href]; if (multiRef == null) { continue; } child.RemoveAttribute("href"); child.InnerXml = multiRef.InnerXml; if (log.IsDebugEnabled) { log.Debug("Replaced multiRef id '" + href + "' with value: " + multiRef.InnerXml); } } } } } public override Stream ChainStream(Stream s) { originalStream = s; newStream = new MemoryStream(); return newStream; } private static void CopyStream(Stream from, Stream to) { TextReader reader = new StreamReader(from); TextWriter writer = new StreamWriter(to); writer.WriteLine(reader.ReadToEnd()); writer.Flush(); } } 

最后,我们标记Reference.cs文件中的所有方法,这些方法将使用我们的属性反序列化长数组:

  [SoapRpcMethod("", RequestNamespace="http://some.service.provider", ResponseNamespace="http://some.service.provider")] [return : SoapElement("getFooReturn")] [LongArrayHelper] public Foo getFoo() { object[] results = Invoke("getFoo", new object[0]); return ((Foo) (results[0])); } 

这个修复是长期特定的,但它可能被推广到处理任何具有此问题的原始类型。

这是我在这个主题上写的一篇或多或少的复制粘贴版本的博客文章 。

执行摘要:您可以更改.NET反序列化结果集的方式(请参阅上面的Chris解决方案),也可以重新配置Axis以与.NET SOAP实现兼容的方式序列化其结果。

如果你走后一条路线,这里是如何:

…生成的类看起来和看起来正常运行,但是如果你看一下客户端(.NET / WCF)端的反序列化数组,你会发现数组已被错误地反序列化,并且所有的值都在数组是0.您必须手动查看Axis返回的SOAP响应,以找出错误; 这是一个示例响应(再次,为清晰起见编辑):

             5 4 3 2 1   

您会注意到Axis不会直接在返回的元素中生成值,而是引用值的外部元素。 当有许多对相对较少的离散值的引用时,这可能是有意义的,但无论如何,WCF basicHttpBinding提供程序都没有正确处理(并且据报道也是由gSOAP和经典的.NET Web引用)。

我花了一段时间才找到解决方案:编辑Axis部署的server-config.wsdd文件并找到以下参数:

  

将其更改为false,然后通过命令行重新部署,该命令行(在Windows下)看起来像这样:

 java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient server-config.wsdl 

现在,您的.NET客户端可以对Web服务的响应进行反序列化。

找到可能提供更好替代方案的链接: http : //www.tomergabel.com/GettingWCFAndApacheAxisToBeFriendly.aspx