Complex Object hosting Array of Complex Objects to .NET Web Service
I am getting a "casting" error on a property of complex object that is sent to a .NET web service using KSOAP2 from an Android device. The property is an array of complex objects. The documentation on the internet has helped me send and receive simple data types (strings, ints, dates, etc). I can even read an array of complex objects from a .NET web service. I just cannot send back an array of complex objects to the web service. Please help. Here is what I have:
Environment: Client = Android Development using the latest KSOAP lib for communication. Server = .NET Web Service (Visual Studio 2008). Note: this is NOT WCF.
.NET Web Service:
[SoapRpcMethod(), WebMethod]
public void WriteCaseInfo(CaseInformation caseInfo)
{
...
...
}
ANDROID CLIENT CODE:
Parent Class Sent as Complex Parameter:
public class CaseInformation extends IABaseKSoap2Serializable
{
public String Name;
public int Id;
public Vector<MultiPartDataElement> SiteListItems = new Vector<MultiPartDataElement>();
@Override
public Object getProperty(int arg0)
{
switch(arg0)
{
case 0:
return Name;
case 1:
return Id;
case 2:
return SiteListItems;
}
return null;
}
@Override
public int getPropertyCount()
{
return 3;
}
@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info)
{
switch(index)
{
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Name";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Id";
break;
case 2:
info.type = new Vector<MultiPartDataElement>().getClass();
info.name = "SiteListItems";
break;
default:break;
}
}
@Override
public void setProperty(int index, Object value)
{
switch(index)
{
case 0:
Name = value.toString();
break;
case 1:
Id = Integer.parseInt(value.toString());
break;
case 2:
SiteListItems = (Vector<MultiPartDataElement>)value;
break;
default:
break;
}
}
}
Note: If I remove the SiteListItems property from the client code and the web service, everything works.
Complex Class used in Array within the above object:public class MultiPartDataElement extends IABaseKSoap2Serializable
{
public int Id;
public String Name;
// default constructor
public MultiPartDataElement()
{
}
// overloaded constructor
public MultiPartDataElement(int id, String name)
{
Id = id;
Name = name;
}
@Override
public Object getProperty(int arg0)
{
switch(arg0)
{
case 0:
return Id;
case 1:
return Name;
}
return null;
}
@Override
public int getPropertyCount()
{
return 2;
}
@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info)
{
switch(index)
{
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Name";
break;
default:break;
}
}
@Override
public void setProperty(int index, Object value)
{
switch(index)
{
case 0:
Id = Integer.parseInt(value.toString());
break;
case 1:
Name = value开发者_高级运维.toString();
break;
default:
break;
}
}
}
Code to Send object as a Parameter to the .Net Web Service:
public static boolean WriteCaseInfo()
{
boolean status = false;
CaseInformation caseInfo = new CaseInformation();
caseInfo.Id = 2725;
caseInfo.Name = "Craig M. Buck";
caseInfo.SiteListItems = new Vector<MultiPartDataElement>();
caseInfo.SiteListItems.add(new MultiPartDataElement(1, "CMB1"));
caseInfo.SiteListItems.add(new MultiPartDataElement(2, "CMB2"));
String methodName = "WriteCaseInfo";
SoapObject request = new SoapObject(NAMESPACE, methodName);
request.addProperty("caseInfo", caseInfo);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = request;
envelope.dotNet = false;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
envelope.addMapping(IABaseKSoap2Serializable.NAMESPACE, "MultiPartDataElement", new MultiPartDataElement().getClass());
envelope.addMapping(IABaseKSoap2Serializable.NAMESPACE, "CaseInformation", new CaseInformation().getClass());
HttpTransportSE transport = new HttpTransportSE(WebAPIURL + CaseServicesURL);
transport.debug = true;
transport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
try
{
List<HeaderProperty> headers = BuildHeader();
transport.call(NAMESPACE + methodName, envelope, headers);
String requestDump = transport.requestDump;
String soapDump = transport.responseDump;
SoapObject response = (SoapObject) envelope.bodyIn;
if(response != null)
status = new Boolean(response.getProperty(0).toString());
}
catch(Exception e)
{
status = false;
}
return status;
}
Request Dump from KSOAP:
<?xml version="1.0" encoding="utf-8"?><v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/"><v:Header /><v:Body><n0:WriteCaseInfo id="o0" c:root="1" xmlns:n0="http://www.medical.draeger.com/webservices/"><caseInfo i:type="n1:CaseInformation" xmlns:n1="http://www.medical.draeger.com/webservices/encodedTypes"><Name i:type="d:string">Craig M. Buck</Name><Id i:type="d:int">2725</Id><SiteListItems i:type="c:Array" c:arrayType="d:anyType[2]"><item i:type="n1:MultiPartDataElement"><Id i:type="d:int">1</Id><Name i:type="d:string">CMB1</Name></item><item i:type="n1:MultiPartDataElement"><Id i:type="d:int">2</Id><Name i:type="d:string">CMB2</Name></item></SiteListItems></caseInfo></n0:WriteCaseInfo></v:Body></v:Envelope>
Note: What I think the issue is, is that the array is defined as "anyTyp" and not MultiPartDataElement -> ... the question is what am I doing wrong here??
Response Dump from KSOAP (After Call):
SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (1, 828). ---> System.InvalidCastException: Cannot assign object of type System.Object[] to an object of type Draeger.IT.Platform.Web.WebServices.MultiPartDataElement[]
I've had similar problem. You might want to try my personal solution.
http://www.codeproject.com/Tips/222578/Android-access-to-NET-Web-Service-with-object-as-p
You could do this:
int propertyCount = countryDetails.getPropertyCount();
ArrayList list = new ArrayList(propertyCount);
lv_arr = new String[propertyCount];
for (int i = 0; i < propertyCount; i++) {
Object property = countryDetails.getProperty(i);
if (property instanceof SoapObject) {
SoapObject countryObj = (SoapObject) property;
String countryName = countryObj.getProperty("countryName").toString();
list.add(countryName);
}
}
from : Parsing ksoap2 response
精彩评论