我正在尝试使用C#来使用SOAP Web服务,并且当使用SOAPUI甚至使用带有SUDS的Python时似乎还可以(我想确保它不在服务器端),而从C#中使用它时,我总是会得到null值(通过Fiddler进行的拦截表明它实际上包含数据)。

可能是C#创建的代理对象未正确处理SOAP数组。

由于我是WSDL的新手,所以我可能错过了一些东西,我在网络上看到许多类似的(与Ladon部分无关)麻烦的解决方法,但是没有什么帮助的。

谢谢你的帮助。



ps:一些代码,因此可以重现此错误。

步骤0:添加:服务Web参考,如此处所述:http://webservices20.blogspot.fr/2008/10/interoperability-gotcha-visual-studio.html
我的被​​称为“ albumsWRn”

此错误的C#演示在这里:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ConsoleApplication6.albumsWRn;    // PUT HERE THE NAME OF THE "Web References" you provide @ step 0

namespace ConsoleApplication6
{
    public static class PrettyPrinter
    {
    // from: http://www.jberndsen.nl/2012/05/c-pretty-printer/

    // the main function to be called to pretty print an object
    public static void PrettyPrint(object myData, StreamWriter sw)
    {
        // output to StreamWriter, in our case, representing a text file
        if (sw == null) throw new ArgumentNullException("sw");
        sw.WriteLines(GetPropValues(myData));
    }

    // to standard output
    public static void PrettyPrint(object myData)
    {
        StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());
        sw.AutoFlush = true;
        Console.SetOut(sw);
        PrettyPrint(myData, sw);
    }

    // extension for the streamwriter to write lists of strings
    private static void WriteLines(this StreamWriter sw, IEnumerable<string> lines)
    {
        foreach (var line in lines)
        {
        sw.WriteLine(line);
        }
    }

    // generates spaces for indentation
    private static string Spaces(int i)
    {
        return (i > 0) ? "    " + Spaces(i - 1) : string.Empty;
    }


    private static string GetValue(object o)
    {
        if (o == null)
        {
        return "null";
        }
        if (o is DateTime)
        {
        return ((DateTime)o).ToShortDateString();
        }
        return o.ToString();
    }


    private static List<string> GetPropValues(object element, int depth = 0)
    {
        var result = new List<string>();
        // primitives
        if (element == null || element is ValueType || element is string)
        {
        result.Add(Spaces(depth) + GetValue(element));
        }
        else
        {
        // enumerations
        var enumerableElement = element as IEnumerable;
        if (enumerableElement != null)
        {
            foreach (var item in enumerableElement)
            {
            result.AddRange(GetPropValues(item, depth + 1));
            }
        }
        // composite types
        else
        {
            // get all the members and iterate through them
            var members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
            foreach (var member in members)
            {
            var fieldInfo = member as FieldInfo;
            var propertyInfo = member as PropertyInfo;
            if (fieldInfo != null || propertyInfo != null)
            {
                // get the type of the member and check if its a primitive
                var t = fieldInfo != null ? fieldInfo.FieldType : propertyInfo.PropertyType;
                if (t.IsValueType || t == typeof(string))
                {
                // print the primitive member, its name and its value
                var localResult = member.Name + ": ";
                localResult += GetValue(fieldInfo != null ? fieldInfo.GetValue(element) : propertyInfo.GetValue(element, null));
                result.Add(Spaces(depth) + localResult);
                }
                else
                {
                // print the non-primitive member, its name and recursively pretty print its value
                var o = fieldInfo != null ? fieldInfo.GetValue(element) : propertyInfo.GetValue(element, null);
                result.Add(Spaces(depth) + member.Name + ": ");
                result.AddRange(GetPropValues(o, depth + 1));
                }
            }
            }
        }
        }
        return result;
    }

    }

    class Program
    {
    static void Main(string[] args)
    {
        AlbumService albumService = new AlbumService();
        var filteredAlbums = albumService.listAlbums("The");
        PrettyPrinter.PrettyPrint(filteredAlbums);
        if (filteredAlbums.item == null)
        {
        Console.WriteLine("null contained, while it should not!");
        }
    }
    }
}


soapUI:这是在使用soapUI检查它实际时使用的查询。

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AlbumService">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:listAlbums soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
     <search-frase xsi:type="xsd:string">The</search-frase>
      </urn:listAlbums>
   </soapenv:Body>
</soapenv:Envelope>


WSDL在这里可见:http://ladonize.org/python-demos/AlbumService/soap11/description
(这是Ladon创作者的演示站点:http://ladonize.org/python-demos/AlbumService

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:AlbumService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns2="urn:AlbumService" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="urn:AlbumService" name="AlbumService">
   <wsdl:types>
      <xsd:schema targetNamespace="urn:AlbumService">
     <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
     <xsd:complexType name="ArrayOfunicode">
        <xsd:sequence>
           <xsd:element type="xsd:string" name="item" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
     </xsd:complexType>
     <xsd:complexType name="Band">
        <xsd:sequence>
           <xsd:element type="ns2:ArrayOfunicode" name="album-titles" nillable="true" minOccurs="0" maxOccurs="1" />
           <xsd:element type="xsd:string" name="name" minOccurs="1" maxOccurs="1" />
        </xsd:sequence>
     </xsd:complexType>
     <xsd:complexType name="Album">
        <xsd:sequence>
           <xsd:element type="ns2:Band" name="band" minOccurs="1" maxOccurs="1" />
           <xsd:element type="ns2:ArrayOfunicode" name="songs" nillable="true" minOccurs="0" maxOccurs="1" />
           <xsd:element type="xsd:string" name="title" minOccurs="1" maxOccurs="1" />
        </xsd:sequence>
     </xsd:complexType>
     <xsd:complexType name="ArrayOfAlbum">
        <xsd:sequence>
           <xsd:element type="ns2:Album" name="item" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
     </xsd:complexType>
     <xsd:complexType name="ArrayOfBand">
        <xsd:sequence>
           <xsd:element type="ns2:Band" name="item" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
     </xsd:complexType>
      </xsd:schema>
   </wsdl:types>
   <wsdl:message name="listAlbums">
      <wsdl:part type="xsd:string" name="search-frase" />
   </wsdl:message>
   <wsdl:message name="listAlbumsResponse">
      <wsdl:part type="ns2:ArrayOfAlbum" name="result" />
   </wsdl:message>
   <wsdl:message name="listBands">
      <wsdl:part type="xsd:string" name="search-frase" />
   </wsdl:message>
   <wsdl:message name="listBandsResponse">
      <wsdl:part type="ns2:ArrayOfBand" name="result" />
   </wsdl:message>
   <wsdl:portType name="AlbumServicePortType">
      <wsdl:operation name="listAlbums">
     <wsdl:documentation>Fetch a list of albums matching search_frase</wsdl:documentation>
     <wsdl:input message="tns:listAlbums" />
     <wsdl:output message="tns:listAlbumsResponse" />
      </wsdl:operation>
      <wsdl:operation name="listBands">
     <wsdl:documentation>Fetch a list of albums matching search_frase</wsdl:documentation>
     <wsdl:input message="tns:listBands" />
     <wsdl:output message="tns:listBandsResponse" />
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding type="tns:AlbumServicePortType" name="AlbumService">
      <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
      <wsdl:operation name="listAlbums">
     <soap:operation style="rpc" soapAction="http://ladonize.org/python-demos/AlbumService/soap11/listAlbums" />
     <wsdl:input>
        <soap:body namespace="urn:AlbumService" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
     </wsdl:input>
     <wsdl:output>
        <soap:body namespace="urn:AlbumService" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
     </wsdl:output>
      </wsdl:operation>
      <wsdl:operation name="listBands">
     <soap:operation style="rpc" soapAction="http://ladonize.org/python-demos/AlbumService/soap11/listBands" />
     <wsdl:input>
        <soap:body namespace="urn:AlbumService" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
     </wsdl:input>
     <wsdl:output>
        <soap:body namespace="urn:AlbumService" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
     </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="AlbumService">
      <wsdl:documentation>Ladon generated service definition</wsdl:documentation>
      <wsdl:port name="AlbumService" binding="tns:AlbumService">
     <soap:address location="http://ladonize.org/python-demos/AlbumService/soap11" />
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>


Fiddler截获的答案(因此,它不是NULL):

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="urn:AlbumService" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <ns:listAlbumsResponse>
     <result>
        <item>
           <band>
          <album-titles>
             <item>Album Of The Year</item>
             <item>KING FOR A DAY - FOOL FOR A LIFETIME</item>
          </album-titles>
          <name>Faith No More</name>
           </band>
           <title>Album Of The Year</title>
           <songs>
          <item>Ashes To Ashes.mp3</item>
          <item>Mouth To Mouth.mp3</item>
          <item>Last Cup Of Sorrow [Sharam Versus Fnm Club Mix] [Bonus Track].mp3</item>
          <item>Paths Of Glory.mp3</item>
          <item>Pristina.mp3</item>
          <item>Light Up And Let Go [Bonus Track].mp3</item>
          <item>Helpless.mp3</item>
          <item>The Big Kahuna [Bonus Track].mp3</item>
          <item>She Loves Me Not.mp3</item>
          <item>Stripsearch.mp3</item>
          <item>Last Cup Of Sorrow.mp3</item>
          <item>Collision.mp3</item>
          <item>Home Sick Home.mp3</item>
          <item>She Loves Me Not [Spinna Crazy Dub Mix] [Bonus Track].mp3</item>
          <item>Last Cup Of Sorrow [Rammstein Mix] [Bonus Track].mp3</item>
          <item>Naked In Front of The Computer.mp3</item>
          <item>Got That Feeling.mp3</item>
          <item>Ashes To Ashes [Hardknox Alternative Mix] [Bonus Track].mp3</item>
           </songs>
        </item>
        <item>
           <band>
          <album-titles>
             <item>Paint The Sky With Stars - The Best Of Enya</item>
          </album-titles>
          <name>Enya</name>
           </band>
           <title>Paint The Sky With Stars - The Best Of Enya</title>
           <songs>
          <item>Watermark.mp3</item>
          <item>Boadicea.mp3</item>
          <item>Storms In Africa.mp3</item>
          <item>Book Of Days.mp3</item>
          <item>Caribben Blue.mp3</item>
          <item>The Celts.mp3</item>
          <item>Anywhere Is.mp3</item>
          <item>Shepherd Moons.mp3</item>
          <item>China Roses.mp3</item>
          <item>Marble Halls.mp3</item>
          <item>On My Way Home.mp3</item>
          <item>Ebudae.mp3</item>
          <item>The Memory Of Trees.mp3</item>
          <item>Paint The Sky With Stars.mp3</item>
          <item>Only If....mp3</item>
          <item>Orinoco Flow.mp3</item>
           </songs>
        </item>
        <item>
           <band>
          <album-titles>
             <item>Zitilites</item>
             <item>No Balance Palace</item>
             <item>Home Dead</item>
             <item>Travelogue</item>
             <item>Cruzential</item>
             <item>The Good Life</item>
          </album-titles>
          <name>Kashmir</name>
           </band>
           <title>The Good Life</title>
           <songs>
          <item>Gorgeous.mp3</item>
          <item>New Year's Eve.mp3</item>
          <item>Lampshade.mp3</item>
          <item>It's OK Now.mp3</item>
          <item>Graceland.mp3</item>
          <item>Miss You.mp3</item>
          <item>Mudbath.mp3</item>
          <item>Mom In Love, Daddy In Space.mp3</item>
          <item>Kiss Me Goodbye.mp3</item>
          <item>Make It Grand.mp3</item>
           </songs>
        </item>
        <item>
           <band>
          <album-titles>
             <item>The Wall CD2</item>
             <item>The Wall Part I</item>
          </album-titles>
          <name>Pink Floyd</name>
           </band>
           <title>The Wall CD2</title>
           <songs>
          <item>Nobody Home.mp3</item>
          <item>Waiting For The Worms.mp3</item>
          <item>Bring The Boys Back Home.mp3</item>
          <item>The Trial.mp3</item>
          <item>Is There Anybody Out There?.mp3</item>
          <item>Comfortably Numb.mp3</item>
          <item>Run Like Hell.mp3</item>
          <item>The Show Must Go On.mp3</item>
          <item>Vera.mp3</item>
          <item>In The Flesh.mp3</item>
          <item>Outside The Wall.mp3</item>
          <item>Hey You.mp3</item>
          <item>Stop.mp3</item>
           </songs>
        </item>
        <item>
           <band>
          <album-titles>
             <item>The Wall CD2</item>
             <item>The Wall Part I</item>
          </album-titles>
          <name>Pink Floyd</name>
           </band>
           <title>The Wall Part I</title>
           <songs>
          <item>The Happiest Days Of Our Lives.mp3</item>
          <item>Another Brick In The Wall (Part 1).mp3</item>
          <item>Goodbye Cruel World.mp3</item>
          <item>One Of The Turns.mp3</item>
          <item>In The Flesh?.mp3</item>
          <item>Empty Spaces.mp3</item>
          <item>The Thin Ice.mp3</item>
          <item>Goodbye Blue Sky.mp3</item>
          <item>Another Brick In The Wall (Part 2).mp3</item>
          <item>Another Brick In The Wall (Part 3).mp3</item>
          <item>Young Lust.mp3</item>
          <item>Mother.mp3</item>
          <item>Don't Leave Now.mp3</item>
           </songs>
        </item>
     </result>
      </ns:listAlbumsResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

最佳答案

当Ladon 0.8.1仅提供RPC / Encoded时,.NET SOAP客户端似乎默认情况下期望Document / Literal WSDL。
我没有找到使C#客户端与RPC / Encoded一起工作的方法,因此我为提供文档/文字WSDL的Ladon(请参见https://bugs.launchpad.net/ladon/+bug/1096004的自定义界面)进行了工作。仅供参考,我遵循了本指南http://wso2.com/library/knowledge-base/convert-rpc-encoded-wsdl-document-literal-wrapped-wsdl

更新:我的修复程序最近在Ladon 0.8.2中生效(请参阅
http://bazaar.launchpad.net/~ladon-dev-team/ladon/ladon/revision/105)。

08-07 04:40