0

I am writing an ios app that talks to the asp.net server by using SOAP web services. one of my web service need to take array of objects. The object definitions are exactly the same on both sides.

Here is what I tried: When I passed just one object as the parameter, the web service worked fine. But as soon as I passed an array of the objects, I got nothing returned. I know the code inside the web service never get called which means the server failed to read the parameters. The wired thing is that the web service returned nothing so I cannot tell what's wrong(I used to get error message from server showing me the stack trace when I did something wrong in the past).

I am not that familiar with SOAP web services so even though I spent a lot of time on MSDN, I still didn't understand what's wrong. After publish the web service, I accessed it through browser. I copied the whole thing to my iOS app so it should work in theory but it never did.

Anyway, this is the server side code:

[System.Web.Services.Protocols.SoapRPCMethod]
[WebMethod(EnableSession = true)]
[XMLInclude(typeof(Team))]
[XMLInclude(typeof(Team[]))]
[SoapInclude(typeof(Team))]
[SoapInclude(typeof(Team[]))]
public string testTeamWebService(Team[] teams) 
{
    // do something here
}

// class definition of Team
[Serializable]
public class Team
{
    public int TeamID;
    public string TeamName;
} 

According to the web service page(.asmx file), here is what I should do to call it:

<?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:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="https://abc.com/" xmlns:types="https://abc.com/encodedTypes" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

    <tns:testTeamWebService>
        <teams href="#id1" />
    </tns:testTeamWebService>

    <soapenc:Array id="id1" soapenc:arrayType="types:Team[2]">
         <Item href="#id2" />
         <Item href="#id3" />
    </soapenc:Array>

   <types:Team id="id2" xsi:type="types:Team">
       <TeamID xsi:type="xsd:int">int</TeamID>
       <TeamName xsi:type="xsd:string">string</TeamName>
   </types:Team>

   <types:Team id="id3" xsi:type="types:Team">
       <TeamID xsi:type="xsd:int">int</TeamID>
       <TeamName xsi:type="xsd:string">string</TeamName>
   </types:Team>
</soap:Body>
</soap:Envelope>

As I said, I constructed the xml and send it in iOS. I used NSMutableURLRequest object and the constructed xml is exactly the way I mentioned above.

In my other web services, I get object arrays from the server so I know .net can serialize the array. This is the first time that my service need to take an array as a parameter, so I think there must be a way of doing it.

Thanks for your reading and please give me some advice if you can.


I finally got the error message from server:

faultcode: soap:Server
 faultstring: System.Web.Services.Protocols.SoapException: Server was unable to process request.---> System.ArgumentException: Object of type 'System.Xml.XmlNode[]' cannot be converted to type 'abc.WebServices.Team[]'.
 at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
 at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
 at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
 at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
 at System.Web.Services.Protocols.LogicalMethodInfo.Invoke(Object target, Object[] values)
 at System.Web.Services.Protocols.WebServiceHandler.Invoke()
 --- End of inner exception stack trace ---
detail: 
Raymond Wang
  • 1,484
  • 2
  • 18
  • 33

2 Answers2

1

I don't really know how to fix your problem, but just in case you can't and need to get it, take a look at http://sudzc.com/ which will generate all the code you will need to make your requests in objective c. I used it and I had some problems when sending arrays too (using sudzc automatic generated classes), but I solved them this way

Community
  • 1
  • 1
Ricard Pérez del Campo
  • 2,387
  • 1
  • 19
  • 22
  • Thanks a lot for your reply. The web service I am doing right now is only on our local test server so I need to publish it to the production. I will give it a try. Thanks. – Raymond Wang Mar 23 '12 at 14:20
0

Here is the solution to my problem. Even though I don't know exactly why my code didn't work, what I know is when the parameter passed to .net server, it tried to guess what's the object I passed. And somehow it got confused of the array of custom objects even though the custom class has been defined and declared at the beginning of the web method.

To solve the real problem, I have a few options: <1> Pass the xml as a string and deserialize it at the server side manually. <2> Pass a dataset of data to the server. <3> Define my class as a XMLNode and pass it to the server.

No matter which way I choose, I have to do some work to deserialize the xml properly.

There is another way to do it.

Since the server was only confused when I used RPC format for my SOAP message, what about another format? I tried the code below, and bingo, the server picked it up right away.

 [WebMethod]
 public string testTeamWebService(Team[] teams) 
{
    // do something here
}


// class definition of Team
[Serializable]
public class Team
{
    public int TeamID;
    public string TeamName;
} 

and then the xml request is formatted in this way:

<?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>
<testTeamWebService xmlns="http://tempuri.org/">
  <teams>
    <Team>
      <TeamID>int</TeamID>
      <TeamName>string</TeamName>
    </Team>
    <Team>
      <TeamID>int</TeamID>
      <TeamName>string</TeamName>
    </Team>
  </teams>
</testTeamWebService>

Here I wanna specially thanks Peter pi - MSFT from Microsoft for helping me with this problem and here is the link on asp.net:

http://forums.asp.net/t/1784291.aspx/1?asp+net+SOAP+RPC+web+method+could+not+read+object+array+parameter

Hope my post can help some people who meets the same problem.

Raymond Wang
  • 1,484
  • 2
  • 18
  • 33