Search code examples
c#soapasmxaxis

Apache Axis client, ASMX service, array incompatibility woes


I have a .Net web service that is called by an Apache Axis client. They're calling a method on our service called getBulkBalance, which gets the balances for players in a game for active players for things like scrolling tickers, etc. The call works fine for a single player request, but not for multiple requests, making getBulkBalance quite... useless, as there is a getBalance method as well.

It's because of the multiple nodes as shown below:

  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
    <soapenv:Header/>
    <soapenv:Body>
      <tem:GetBulkBalanceRequest>
         <!--Optional:-->
         <tem:secureLogin>login</tem:secureLogin>
         <!--Optional:-->
         <tem:securePassword>password</tem:securePassword>
         <!--Zero or more repetitions:-->
         <tem:playerIDList>60</tem:playerIDList>
         <tem:playerIDList>61</tem:playerIDList>
      </tem:GetBulkBalanceRequest>
   </soapenv:Body>
 </soapenv:Envelope>

If they call with only one, it works fine. If they passed in 60,61 in one node, it works fine. The other side will not/can not change the way their client handles arrays of Int64s.

My method looks like this:

    [WebMethod]
    [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare, Action = "GetBulkBalance")]
    [return: XmlElement(ElementName = "GetBulkBalanceResponse")]
    public GetBulkBalanceResponse GetBulkBalance(GetBulkBalanceRequest GetBulkBalanceRequest)

GetBulkBalanceRequest is as follows:

[Serializable]
public class GetBulkBalanceRequest
{
    [XmlElement(Namespace = Constants.ServiceNamespace)]
    public string secureLogin;
    [XmlElement(Namespace = Constants.ServiceNamespace)]
    public string securePassword;
    [XmlElement(Namespace = Constants.ServiceNamespace)]
    public Int64[] playerIDList;
}

Any ideas on how to get Axis and WCF to play nice? Maybe some attribute I am missing? Thanks in advance!


Solution

  • Derreck,

    If nothing has to changed in the client, may be you could declare your list as a string and make the parsing in your server code ?

    [Serializable]
    public class GetBulkBalanceRequest
    {
        // ....
        [XmlElement(Namespace = Constants.ServiceNamespace)]
        public String playerIDList;
    }
    

    Your server code would be :

    [WebService(Namespace = Constants.ServiceNamespace)]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class WebService1 : System.Web.Services.WebService
    {
        [WebMethod]
        [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare, Action = "GetBulkBalance")]
        [return: XmlElement(ElementName = "GetBulkBalanceResponse")]
        public GetBulkBalanceResponse GetBulkBalance(GetBulkBalanceRequest getBulkBalanceRequest)
        {
            Int64 [] ids = getBulkBalanceRequest.playerIDList
                                .Split(',')
                                .Select(s => Int64.Parse(s)).ToArray();
            return new GetBulkBalanceResponse { responseValue = "response42" };
        }
    }
    

    From what I see, you are writing an ASMX service, not a "real" WCF service. With WCF, you could parse the body of the message in a message inspector :

    1. IClientMessageInspector for the client side of course
    2. IDispatcherMessageInspector on the server side

    Hope it helps