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 ArrayItem
s. 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?