WCF, NuSOAP and ArrayOfString

By Jerome at April 16, 2007 15:21
Filed Under: .NET

When exposing a WebService via WCF, you might want to expose something like this :


[DataContract]
public class SomeContract
{
  [DataMember] 
  public string[] Values { get; set; }
}

For that particular data contract, WCF will be generating a WSDL with something like this :


<xs:complexType name="SomeContract">

  <xs:sequence>

    <xs:element minOccurs="0" name="Values" nillable="true"

                type="q1:ArrayOfstring"

                xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />

  </xs:sequence>

</xs:complexType>

With ArrayOfString being defined like this :


  <xs:schema elementFormDefault="qualified"

             targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"

             xmlns:xs="http://www.w3.org/2001/XMLSchema"

             xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

    <xs:complexType name="ArrayOfstring">

      <xs:sequence>

        <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string"/>

      </xs:sequence>

    </xs:complexType>

    <xs:element name="ArrayOfstring" nillable="true" type="tns:ArrayOfstring"/>

  </xs:schema>

In general, that would be fine. The type "ArrayOfString" is defined in a different namespace, but this should not be a problem.

So, to use that particular type in a method call, you should have a document like this one :


<SomeContract>

  <Values xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

    <a:string>My Value</a:string>

  </Values>

</SomeContract>

"string" elements are contained in a different namespace from the SomeContract element. However, the NuSOAP stock version 0.7.2 has a problem with that kind of schema, and generates instead something like this :


<SomeContract>

  <Values>

    <string>My Value</string>

  </Values>

</SomeContract>


When the WCF deserializer receives a document like this one, it does not find the "Values" member in the namespace he's looking and ends up creating a SomeContract instance with a null array of strings.

Since there's no way of fixing NuSOAP, you may need to tweak your contract to help NuSOAP serializing your data without a namespace.

The CollectionDataContract attribute seems to be the way to go, since there is a way to specify the namespace to use when generating the metadata. The service contract then looks like this :


  [DataContract(Namespace = "http://my.name.space")] 
  public class SomeContract 
  { 
    [DataMember] 
    public ArrayOfString InvalidIdentifiers { get; set; } 
  } 

  [CollectionDataContract(ItemName="string", Namespace="http://my.name.space")]
  public class ArrayOfString : List<string> { } 

Thereby placing everything in the "http://my.name.space" namespace.

You might need to tweak a bit the ArrayOfString class, especially if you need to assign it from an actual string[] instance, but you get the idea.

Comments

1/22/2009 4:59:35 AM #

Bonjour,
ton article est très interressant et m'a pas mal aidé.
J'aimererai produire un résultat de ce type :
<SomeContract>
  <Value>Valeur 1</Value>
  <Value>Valeur 2</Value>
  <Value>Valeur 3</Value>
  <Value>Valeur 4</Value>
</SomeContract>

à partir d'une class de ce type :
[DataContract]
public class Test
{
[DataMember]
    public ArrayOfString Value { get; set; }
}

Est ce possible ?

Merci

Verriere David France

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading




About me

My name is Jerome Laban, I am a Software developer and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Bluetooth Remote Control Software for Windows Mobile.