title: How can I fix the web reference proxy that Visual Studio generated to handle jagged arrays?
body: <p>It seems there is a known bug in wsdl.exe, the tool that Visual Studio uses to generate web service proxies. With certain XSD schemas the tool will generate classes that can't be deserialized from the XML.</p>
  
  <p>As far as I'm concerned that's unacceptable, but I don't know how to fix it. </p>
  
  <p>I will describe my case in detail, hopefully somebody will be able to help me with it.</p>
  
  <p><strong>Schema</strong></p>
  
  <pre><code>&lt;!-- return type from the service operation --&gt;
  &lt;xs:complexType name="listAssetsQueryResults"&gt;
      &lt;xs:sequence&gt;
          &lt;xs:element name="assets" type="tns:asset" minOccurs="0" maxOccurs="unbounded"/&gt;
      &lt;/xs:sequence&gt;
  &lt;/xs:complexType&gt;
  
  &lt;!-- a sequence of attributes --&gt;
  &lt;xs:complexType name="asset"&gt;
      &lt;xs:sequence&gt;
          &lt;xs:element name="attributes" type="tns:multiValuedAttribute" minOccurs="0" maxOccurs="unbounded"/&gt;
      &lt;/xs:sequence&gt;
  &lt;/xs:complexType&gt;
  
  &lt;xs:complexType name="multiValuedAttribute"&gt;
      &lt;!-- not relevant--&gt;
  &lt;/xs:complexType&gt;
  </code></pre>
  
  <p><strong>XML response from the webservice</strong></p>
  
  <p>A typical response according to this schema looks like this:</p>
  
  <pre><code>&lt;assets-query-result&gt;
      &lt;assets&gt;
          &lt;attributes&gt;
              &lt;name&gt;Keywords&lt;/name&gt;
              &lt;values&gt;Desert&lt;/values&gt;
          &lt;/attributes&gt;
          &lt;attributes&gt;
              &lt;name&gt;Filename&lt;/name&gt;
              &lt;values&gt;Desert.jpg&lt;/values&gt;
          &lt;/attributes&gt;
      &lt;/assets&gt;
      &lt;assets&gt;...&lt;/assets&gt;
      &lt;assets&gt;...&lt;/assets&gt;
  &lt;/assets-query-result&gt;
  </code></pre>
  
  <p><strong>Using the types in code</strong></p>
  
  <p>I would have expected to be able to use the CLR types like this:</p>
  
  <pre><code>result.assets[0].attributes[0].name
  </code></pre>
  
  <p>Instead, the generated type for the result looks like this:</p>
  
  <pre><code>[SerializableAttribute()]
  public partial class listAssetsQueryResults {
      private multiValuedAttribute[][] assetsField;
  
      [XmlArrayAttribute(Form=XmlSchemaForm.Unqualified, IsNullable=true)]
      [XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute), Form=XmlSchemaForm.Unqualified)]
      public multiValuedAttribute[][] assets {
          get { return this.assetsField; }
          set { this.assetsField = value; }
      }
  }
  </code></pre>
  
  <p>Which doesn't even allow the serialization assembly to be generated! </p>
  
  <blockquote>
    <p>Unable to convert type
    Portfolio.WebService.multiValuedAttribute
    to Portfolio.WebService.multiValuedAttribute[]</p>
  </blockquote>
  
  <p><strong>Fixing it</strong></p>
  
  <p>1 - Changing the type of the property and field</p>
  
  <p>Now one of the fixes I found online is simply to remove one pair of brackets from the type of the generated property:</p>
  
  <pre><code>// No longer a jagged array, but this doesn't deserialize all data
  public multiValuedAttribute[] assets;
  </code></pre>
  
  <p>That allows the serialization assembly to be built, and it runs without exceptions, except it doesn't serialize the data correctly, it 'skips' the list of assets and deserializes the attributes of the first <code>assets</code> element. So it's not a fix at all, because with this fix I can't consume the data. For 700+ assets it gives <code>result.assets</code> is equal to <code>multiValuedAttribute[2]</code> (the 2 elements are the name and keywords attributes of the first asset).</p>
  
  <p>2 - Specifying the type of the XML-elements</p>
  
  <p>The second thing I tried is to give the deserializer different instructions:</p>
  
  <pre><code>[XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute[]), Form=XmlSchemaForm.Unqualified)]
  public multiValuedAttribute[][] assets { ... }
  </code></pre>
  
  <p>So now I'm telling it that each element in the sequence is of type <code>multiValuedAttribute[]</code>. That's wrong because it's still looking at <code>attributes</code> elements, which are of type <code>multiValuedAttribute</code> (single, not an array). It does run however, but now the <code>result.assets</code> is equal to <code>multiValuedAttribute[2][0]</code> and I'm still not able to get to the data.</p>
  
  <p><strong>What's next?</strong></p>
  
  <p>I have no idea, which is why I wrote this. I can't accept that .NET is not able to consume this web service, because it has to. </p>