C# – control the XML element names for an array and its items as the return value from an asynchronous .Net ASMX web method

asmxasynchronouscnetweb services

Consider the following .Net ASMX web service with two web methods.

using System;
using System.Runtime.Remoting.Messaging;
using System.Web.Services;
using System.Xml.Serialization;

namespace DemoWebService
{
 public class
 ArrayItem
 {
  public int
  Value1;

  public int
  Value2;
 };

 [WebService(Namespace = "http://begen.name/xml/namespace/2009/09/demo-web-service/")]
 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
 public class DemoService :
  WebService
 {
  [WebMethod]
  [return: XmlArray("Items")]
  [return: XmlArrayItem("Item")]
  public ArrayItem []
  GetArray()
  {
   return BuildArray();
  }

  [WebMethod]
  public IAsyncResult
  BeginGetArrayAsync(AsyncCallback callback, object callbackData)
  {
   BuildArrayDelegate fn = BuildArray;
   return fn.BeginInvoke(callback, callbackData);
  }

  [WebMethod]
  [return: XmlArray("Items")]
  [return: XmlArrayItem("Item")]
  public ArrayItem []
  EndGetArrayAsync(IAsyncResult result)
  {
   BuildArrayDelegate fn = (BuildArrayDelegate)((AsyncResult)result).AsyncDelegate;
   return fn.EndInvoke(result);
  }

  private delegate ArrayItem []
  BuildArrayDelegate();

  private ArrayItem []
  BuildArray()
  {
   ArrayItem [] retval = new ArrayItem[2];
   retval[0] = new ArrayItem();
   retval[0].Value1 = 1;
   retval[0].Value2 = 2;
   retval[1] = new ArrayItem();
   retval[1].Value1 = 3;
   retval[1].Value2 = 4;

   return retval;
  }
 }
}

The GetArray and GetArrayAsync web methods both return an array of ArrayItems. The GetArrayAsync web method, however, is implemented using the asynchronous programming model.

Through the use of the [XmlArray] and [XmlArrayItem] attributes applied to the return value of the GetArray() method, I've been able to control the XML elements .Net uses to serialize the return value and get a result like this:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetArrayResponse xmlns="http://begen.name/xml/namespace/2009/09/demo-web-service/">
      <Items>
        <Item>
          <Value1>int</Value1>
          <Value2>int</Value2>
        </Item>
        <Item>
          <Value1>int</Value1>
          <Value2>int</Value2>
        </Item>
      </Items>
    </GetArrayResponse>
  </soap:Body>
</soap:Envelope>

Notice how the return value has the XML element name of "Items" and each item in the array has the XML element name of "Item".

I have applied the same attributes to the EndGetArrayAsync() method, but they don't seem to affect the response the way they do for the synchronous GetArray() method. In this case the response looks like this:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetArrayAsyncResponse xmlns="http://begen.name/xml/namespace/2009/09/demo-web-service/">
      <GetArrayAsyncResult>
        <ArrayItem>
          <Value1>int</Value1>
          <Value2>int</Value2>
        </ArrayItem>
        <ArrayItem>
          <Value1>int</Value1>
          <Value2>int</Value2>
        </ArrayItem>
      </GetArrayAsyncResult>
    </GetArrayAsyncResponse>
  </soap:Body>
</soap:Envelope>

In this case, the return value was given the default XML element name of "GetArrayAsyncResult" and the array items have the XML element name coming from the C# class name, "ArrayItem".

Is there any way to get an asynchronous web method to respect the [XmlArray] and [XmlArrayItem] attributes applied to the return value of the End* method?

Best Answer

See this question...

You need to add the XmlType() attribute to the class used in the array and then specify only the XmlArray() attribute on the class member defining the array.

Related Topic