I'm building my first application in android which consumes a wcf service.I'm using ksoap2 to parse the response.The response is actually an array of objects defined in C#.I did this following this really helpful guide.Now my problem is that I need to consume a wcf service which returns again an array of objects in C# but this time some properties of these objects are other objects.So my question is how can I map the inner objects so that i can parse their properties?
In case I was unclear, I need to parse an object like this:
public class OutterObject {
private InnerObject1 io1;
private InnerObject2 io2;
}
Hope I was clear enough
Ok this is my simplified code i can't post all of it just the portion i think is at fault
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty("connString",args.get(0));
Request.addProperty("ClCode", args.get(1));
Request.addProperty("TeCode", args.get(2));
Request.addProperty("CourseDate", args.get(3));
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
envelope.addMapping(namespace, "SRV_WeekProgramm",newSRV_WeekProgramm().getClass());
envelope.addMapping(namespace, "Course", new Course().getClass());
envelope.addMapping(namespace, "StudentHours", new StudentHours().getClass());
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
Course response = (Course)envelope.bodyIn; //this is where it crashes
and this is the thrown exception: java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to connectionInitializer.Course
Here is an example that worked for me.
This is response message type from web service
<message name="loginUserResponse">
<part name="code" type="xsd:int"/>
<part name="desc" type="xsd:string"/>
<part name="user" type="tns:user"/>
</message>
The method loginUser definition
<operation name="loginUser">
<documentation>Login user.</documentation>
<input message="tns:loginUserRequest"/>
<output message="tns:loginUserResponse"/>
</operation>
Class UserResponse (Outter) contains User property:
public class UserResponse implements KvmSerializable {
public int code;
public String desc;
public User user;
public Object getProperty(int arg0) {
switch (arg0) {
case 0:
return code;
case 1:
return desc;
case 2:
return user;
default:
break;
}
return null;
}
public int getPropertyCount() {
return 3;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "code";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "desc";
break;
case 2:
info.type = User.class;
info.name = "user";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
this.code = Integer.parseInt(value.toString());
break;
case 1:
this.desc = value.toString();
break;
case 2:
this.user = (User) value;
default:
break;
}
}
}
And the User class (Inner)
public class User implements KvmSerializable {
public int user_id;
public String username;
public String email;
public String password;
public User() {
}
public Object getProperty(int index) {
switch (index) {
case 0:
return user_id;
case 1:
return username;
case 2:
return email;
case 3:
return password;
default:
return null;
}
}
public int getPropertyCount() {
return 4;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "user_id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "username";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "email";
break;
case 3:
info.type = PropertyInfo.STRING_CLASS;
info.name = "password";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
if(null == value)
value = "";
switch (index) {
case 0:
user_id = Integer.parseInt(value.toString());
break;
case 1:
username = value.toString();
break;
case 2:
email = value.toString();
break;
case 3:
password = value.toString();
break;
}
}
This is important: make sure you register the keys for both outter class and inner class.
envelope.addMapping(NAMESPACE, "loginUserResponse", UserResponse.class);
envelope.addMapping(NAMESPACE, "user", User.class);
Finally, you can get the result by casting:
HttpTransportSE androidHttpTransport = new HttpTransportSE(SERVER_URL); //open the requisition
androidHttpTransport.call(SOAP_ACTION, envelope);// call
UserResponse response = (UserResponse)envelope.bodyIn;
Hope this help!
Related
So, I am a newbie in mobile development and interoperability. I am developing a Android application that comunnicates send a Contact object to a remove server that is running a .NET Web Service (via kSOAP). But there is a 500 error in the server and I really don't know how to map it because it is running remotely and my host plan doesn't allow me to debug remotely. I believe it is an error in the interpretation of the Java object in the ASP.NET Web Service, I don't know if it is necessary to deserialize the object and how to do it. I hope that a more experienced developer could help me. I already used primitive objects (string, int and others) and it worked like a charm but I really prefer to work with my models.
The Android Application - Call of the Web Service:
public int webServiceMethodRegisterUser(String... paramss)
{
String resultData;
try {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
Contact c = new Contact(paramss[0], paramss[1]);
c._email = paramss[0];
c._password = paramss[1];
c._cellphonesim = paramss[2];
c._simoperator = paramss[3];
PropertyInfo pi = new PropertyInfo();
pi.setName("contact");
pi.setValue(c);
pi.setType(c.getClass());
request.addProperty(pi);
//request.addProperty("useremail", paramss[0]);
//request.addProperty("userpass", paramss[1]);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet=true;
envelope.setOutputSoapObject(request);
envelope.addMapping(NAMESPACE, "Contact" , new Contact().getClass());
//Marshal floatMarshal = new Marshal();
//floatMarshal.register(envelope);
//Marshal oi = new ();
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
Object result=(Object)envelope.getResponse();
//To get the data.
resultData= result.toString();
publishProgress(resultData);
return Integer.parseInt(resultData);
} catch (Exception e) {
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
throw new RuntimeException(e1.toString());
}
throw new RuntimeException(e.toString());
}
}
Custom Object in Java
package com.example.ivi;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.MarshalDate;
import org.ksoap2.serialization.PropertyInfo;
public class Contact implements KvmSerializable {
// private variables
int _id;
String _email;
String _password;
String _simoperator;
String _cellphonesim;
String _sn_facebook;
String _sn_linkedin;
String _sn_googleplus;
String _sn_orkut;
String _sn_twitter;
Date _last_refresh;
Date _register_date;
public Contact(int id, String email, String password, String simoperator,
String cellphonesim, String facebook, String linkedin,
String googleplus, String orkut, String twitter, Date refreshuser,
Date userregister) {
_id = id;
_email = email;
_password = password;
_simoperator = simoperator;
_cellphonesim = cellphonesim;
_sn_facebook = facebook;
_sn_linkedin = linkedin;
_sn_googleplus = googleplus;
_sn_orkut = orkut;
_sn_twitter = twitter;
_last_refresh = refreshuser;
_register_date = userregister;
}
public Contact() {
}
// constructor
public Contact(int id, String email, String password) {
this._id = id;
this._email = email;
this._password = password;
}
// constructor
public Contact(String email, String password) {
this._email = email;
this._password = password;
}
#Override
public Object getProperty(int arg0) {
switch (arg0) {
case 0:
return _id;
case 1:
return _email;
case 2:
return _password;
case 3:
return _simoperator;
case 4:
return _cellphonesim;
case 5:
return _sn_facebook;
case 6:
return _sn_linkedin;
case 7:
return _sn_googleplus;
case 8:
return _sn_orkut;
case 9:
return _sn_twitter;
case 10:
return _last_refresh;
case 11:
return _register_date;
}
return null;
}
#Override
public int getPropertyCount() {
// TODO Auto-generated method stub
return 12;
}
#Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "UserId";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserEmail";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserPassword";
break;
case 3:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserSimOperator";
break;
case 4:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserCellPhoneSim";
break;
case 5:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserFacebook";
break;
case 6:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserLinkedin";
break;
case 7:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserGoogleplus";
break;
case 8:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserOrkut";
break;
case 9:
info.type = PropertyInfo.STRING_CLASS;
info.name = "UserTwitter";
break;
case 10:
info.type = MarshalDate.DATE_CLASS;
;
info.name = "UserLastRefresh";
break;
case 11:
info.type = MarshalDate.DATE_CLASS;
;
info.name = "UserRegisterDate";
break;
}
}
#Override
public void setProperty(int index, Object value) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
switch (index) {
case 0:
_id = Integer.parseInt(value.toString());
break;
case 1:
_email = value.toString();
break;
case 2:
_password = value.toString();
break;
case 3:
_simoperator = value.toString();
break;
case 4:
_cellphonesim = value.toString();
break;
case 5:
_sn_facebook = value.toString();
break;
case 6:
_sn_linkedin = value.toString();
break;
case 7:
_sn_googleplus = value.toString();
break;
case 8:
_sn_orkut = value.toString();
break;
case 9:
_sn_twitter = value.toString();
break;
case 10:
try {
_last_refresh = formatter.parse(value.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case 11:
try {
_register_date = formatter.parse(value.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
. NET Web Service
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
namespace WebServiceIvi
{
[WebService(Namespace = "http://www.ividomain.somee.com/Service1")]
[WebServiceBinding(ConformsTo = WsiProfiles.None)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public int registerUser(Contact contato)
{
string connString = CONNECTION_STRING;
SqlConnection con = new SqlConnection(connString);
SqlCommand cmdSQL = con.CreateCommand();
try
{
con.Open();
cmdSQL.CommandText = String.Format("INSERT INTO [databaseivi].[dbo].[UsersIvi] ([Useremail],[Userpass],[Userxml],[Usersince]) VALUES('{0}','{1}',null ,getDate())", contato.UserEmail, contato.UserPassword);
int result = cmdSQL.ExecuteNonQuery();
con.Close();
return result;
}
catch (SqlException e)
{
foreach (SqlError error in e.Errors)
{
return error.Number;
}
return 0;
}
}
}
}
The Custom Object in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebServiceIvi
{
public class Contact
{
public Contact(int id, String email, String password, String simoperator, String cellphonesim, String facebook, String linkedin, String googleplus, String orkut, String twitter, DateTime refreshuser, DateTime userregister )
{
_id = id;
_email = email;
_password = password;
_simoperator = simoperator;
_cellphonesim = cellphonesim;
_sn_facebook = facebook;
_sn_linkedin = linkedin;
_sn_googleplus = googleplus;
_sn_orkut = orkut;
_sn_twitter = twitter;
_last_refresh = refreshuser;
_register_date = userregister;
}
public Contact()
{
}
int _id;
String _email;
String _password;
String _simoperator;
String _cellphonesim;
String _sn_facebook;
String _sn_linkedin;
String _sn_googleplus;
String _sn_orkut;
String _sn_twitter;
DateTime _last_refresh;
DateTime _register_date;
public int UserId
{
set { _id = value; }
get
{
if (_id <= 0) return _id;
else return 0;
}
}
public string UserEmail
{
set { _email = value; }
get
{
if (_email != null) return _email.ToString();
else return string.Empty;
}
}
public string UserPassword
{
set { _password = value; }
get
{
if (_password != null) return _password.ToString();
else return string.Empty;
}
}
public string UserSimOperator
{
set { _simoperator = value; }
get
{
if (_simoperator != null) return _simoperator.ToString();
else return string.Empty;
}
}
public string UserCellPhoneSim
{
set { _cellphonesim = value; }
get
{
if (_cellphonesim != null) return _cellphonesim.ToString();
else return string.Empty;
}
}
public string UserFacebook
{
set { _sn_facebook = value; }
get
{
if (_sn_facebook != null) return _sn_facebook.ToString();
else return string.Empty;
}
}
public string UserLinkedin
{
set { _sn_linkedin = value; }
get
{
if (_sn_linkedin != null) return _sn_linkedin.ToString();
else return string.Empty;
}
}
public string UserGoogleplus
{
set { _sn_googleplus = value; }
get
{
if (_sn_googleplus != null) return _sn_googleplus.ToString();
else return string.Empty;
}
}
public string UserOrkut
{
set { _sn_orkut = value; }
get
{
if (_sn_orkut != null) return _sn_orkut.ToString();
else return string.Empty;
}
}
public string UserTwitter
{
set { _sn_twitter = value; }
get
{
if (_sn_twitter != null) return _sn_twitter.ToString();
else return string.Empty;
}
}
public DateTime UserLastRefresh
{
set { _last_refresh = value; }
get
{
if (_last_refresh != null) return DateTime.Parse(_last_refresh.ToString());
else return DateTime.MinValue;
}
}
public DateTime UserRegisterDate
{
set { _register_date = value; }
get
{
if (_register_date != null) return DateTime.Parse(_register_date.ToString());
else return DateTime.MinValue;
}
}
}
}
The SOAP Request XML:
POST /Service1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.ividomain.somee.com/Service1/registerUser"
<?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>
<registerUser xmlns="http://www.ividomain.somee.com/Service1">
<contato>
<UserId>int</UserId>
<UserEmail>string</UserEmail>
<UserPassword>string</UserPassword>
<UserSimOperator>string</UserSimOperator>
<UserCellPhoneSim>string</UserCellPhoneSim>
<UserFacebook>string</UserFacebook>
<UserLinkedin>string</UserLinkedin>
<UserGoogleplus>string</UserGoogleplus>
<UserOrkut>string</UserOrkut>
<UserTwitter>string</UserTwitter>
<UserLastRefresh>dateTime</UserLastRefresh>
<UserRegisterDate>dateTime</UserRegisterDate>
</contato>
</registerUser>
</soap:Body>
</soap:Envelope>
I've been stuck in this for a while and didn't found any implementation and deserialization of a java model in .NET. I hope someone out there helps me! =D
ThiagoMello, I had this error days ago and solve it generting java class from this site:
http://www.wsdl2code.com/Pages/Home.aspx
With this classes my code works fine! Try it.
Hope this helps.
Joan.
I am trying to send a complex object through a soap service call in an android application. I am getting a quite weird error.
The class that I am trying to serialize and send (and the one that are included to it) is the following:
public class TSavedMessage extends BaseObject{
public static Class TSAVEDMESSAGE_CLASS = new TSavedMessage().getClass();
protected String sToken;
protected String dateDeferredDelivery;
protected int idDepartment;
protected boolean bDraft;
protected String txtRelationsType;
protected String txtRelatedIds;
protected int idForwardOf;
protected int idReplyOf;
protected String numPriority;
protected boolean bReadReceipt;
protected boolean bDeliveryReport;
protected String txtKeywords;
protected int numTimeOffset;
protected String txtTimeZone;
protected String txtSubject;
protected String txtBody;
protected TRecipient[] recipients;
public TSavedMessage() {
}
public TSavedMessage(String sToken, String dateDeferredDelivery, int idDepartment, boolean bDraft, String txtRelationsType, String txtRelatedIds, int idForwardOf, int idReplyOf, String numPriority, boolean bReadReceipt, boolean bDeliveryReport, String txtKeywords, int numTimeOffset, String txtTimeZone, String txtSubject, String txtBody, TRecipient[] recipients, int[] vesselRelations) {
this.sToken = sToken;
this.dateDeferredDelivery = dateDeferredDelivery;
this.idDepartment = idDepartment;
this.bDraft = bDraft;
this.txtRelationsType = txtRelationsType;
this.txtRelatedIds = txtRelatedIds;
this.idForwardOf = idForwardOf;
this.idReplyOf = idReplyOf;
this.numPriority = numPriority;
this.bReadReceipt = bReadReceipt;
this.bDeliveryReport = bDeliveryReport;
this.txtKeywords = txtKeywords;
this.numTimeOffset = numTimeOffset;
this.txtTimeZone = txtTimeZone;
this.txtSubject = txtSubject;
this.txtBody = txtBody;
this.recipients = recipients;
}
public String getSToken() {
return sToken;
}
public void setSToken(String sToken) {
this.sToken = sToken;
}
public String getDateDeferredDelivery() {
return dateDeferredDelivery;
}
public void setDateDeferredDelivery(String dateDeferredDelivery) {
this.dateDeferredDelivery = dateDeferredDelivery;
}
public int getIdDepartment() {
return idDepartment;
}
public void setIdDepartment(int idDepartment) {
this.idDepartment = idDepartment;
}
public boolean isBDraft() {
return bDraft;
}
public void setBDraft(boolean bDraft) {
this.bDraft = bDraft;
}
public String getTxtRelationsType() {
return txtRelationsType;
}
public void setTxtRelationsType(String txtRelationsType) {
this.txtRelationsType = txtRelationsType;
}
public String getTxtRelatedIds() {
return txtRelatedIds;
}
public void setTxtRelatedIds(String txtRelatedIds) {
this.txtRelatedIds = txtRelatedIds;
}
public int getIdForwardOf() {
return idForwardOf;
}
public void setIdForwardOf(int idForwardOf) {
this.idForwardOf = idForwardOf;
}
public int getIdReplyOf() {
return idReplyOf;
}
public void setIdReplyOf(int idReplyOf) {
this.idReplyOf = idReplyOf;
}
public String getNumPriority() {
return numPriority;
}
public void setNumPriority(String numPriority) {
this.numPriority = numPriority;
}
public boolean isBReadReceipt() {
return bReadReceipt;
}
public void setBReadReceipt(boolean bReadReceipt) {
this.bReadReceipt = bReadReceipt;
}
public boolean isBDeliveryReport() {
return bDeliveryReport;
}
public void setBDeliveryReport(boolean bDeliveryReport) {
this.bDeliveryReport = bDeliveryReport;
}
public String getTxtKeywords() {
return txtKeywords;
}
public void setTxtKeywords(String txtKeywords) {
this.txtKeywords = txtKeywords;
}
public int getNumTimeOffset() {
return numTimeOffset;
}
public void setNumTimeOffset(int numTimeOffset) {
this.numTimeOffset = numTimeOffset;
}
public String getTxtTimeZone() {
return txtTimeZone;
}
public void setTxtTimeZone(String txtTimeZone) {
this.txtTimeZone = txtTimeZone;
}
public String getTxtSubject() {
return txtSubject;
}
public void setTxtSubject(String txtSubject) {
this.txtSubject = txtSubject;
}
public String getTxtBody() {
return txtBody;
}
public void setTxtBody(String txtBody) {
this.txtBody = txtBody;
}
public TRecipient[] getRecipients() {
return recipients;
}
public void setRecipients(TRecipient[] recipients) {
this.recipients = recipients;
}
public Object getProperty(int index) {
switch (index) {
case 0:
return sToken;
case 1:
return dateDeferredDelivery;
case 2:
Integer iDepartment = new Integer(idDepartment);
return iDepartment;
case 3:
Boolean isDraft = new Boolean(bDraft);
return isDraft;
case 4:
return txtRelationsType;
case 5:
return txtRelatedIds;
case 6:
Integer iForwardOf = new Integer(idForwardOf);
return iForwardOf;
case 7:
Integer iReplyOf = new Integer(idReplyOf);
return iReplyOf;
case 8:
return numPriority;
case 9:
Boolean isReadReceipt = new Boolean(bReadReceipt);
return isReadReceipt;
case 10:
Boolean isDeliveryReport = new Boolean(bDeliveryReport);
return isDeliveryReport;
case 11:
return txtKeywords;
case 12:
Integer iTimeOffset = new Integer(numTimeOffset);
return iTimeOffset;
case 14:
return txtTimeZone;
case 15:
return txtSubject;
case 16:
return txtBody;
case 17:
return recipients; // complex type
default:
return null;
}
}
public int getPropertyCount() {
return 18;
}
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "sToken";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "dateDeferredDelivery";
break;
case 2:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idDepartment";
break;
case 3:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bDraft";
break;
case 4:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRelationsType";
break;
case 5:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRelatedIds";
break;
case 6:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idForwardOf";
break;
case 7:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idReplyOf";
break;
case 8:
info.type = PropertyInfo.STRING_CLASS;
info.name = "numPriority";
break;
case 9:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bReadReceipt";
break;
case 10:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bDeliveryReport";
break;
case 11:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtKeywords";
break;
case 12:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "numTimeOffset";
break;
case 14:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtTimeZone";
break;
case 15:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtSubject";
break;
case 16:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtBody";
break;
case 17:
info.type = PropertyInfo.VECTOR_CLASS;
info.name = "recipients"; // complex type
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
sToken = value.toString();
break;
case 1:
dateDeferredDelivery = value.toString();
break;
case 2:
idDepartment = Integer.parseInt(value.toString());
break;
case 3:
if(value.toString().equalsIgnoreCase("false")) bDraft = false;
else bDraft = true;
break;
case 4:
txtRelationsType = value.toString();
break;
case 5:
txtRelatedIds = value.toString();
break;
case 6:
idForwardOf = Integer.parseInt(value.toString());
break;
case 7:
idReplyOf = Integer.parseInt(value.toString());
break;
case 8:
numPriority = value.toString();
break;
case 9:
if(value.toString().equalsIgnoreCase("false")) bReadReceipt = false;
else bReadReceipt = true;
break;
case 10:
if(value.toString().equalsIgnoreCase("false")) bDeliveryReport = false;
else bDeliveryReport = true;
break;
case 11:
txtKeywords = value.toString();
break;
case 12:
numTimeOffset = Integer.parseInt(value.toString());
break;
case 14:
txtTimeZone = value.toString();
break;
case 15:
txtSubject = value.toString();
break;
case 16:
txtBody = value.toString();
break;
case 17:
recipients = (TRecipient[]) value; // complex type
break;
default:
break;
}
}
}
public class TRecipient extends BaseObject{
public static Class TRECIPIENT_CLASS = new TRecipient().getClass();
protected int idRecipient;
protected String txtRealAddress;
protected String Visibility;
public TRecipient() {
}
public TRecipient(int idRecipient, String txtRealAddress, String visibility) {
this.idRecipient = idRecipient;
this.txtRealAddress = txtRealAddress;
this.Visibility = visibility;
}
public int getIdRecipient() {
return idRecipient;
}
public void setIdRecipient(int idRecipient) {
this.idRecipient = idRecipient;
}
public String getTxtRealAddress() {
return txtRealAddress;
}
public void setTxtRealAddress(String txtRealAddress) {
this.txtRealAddress = txtRealAddress;
}
public String getVisibility() {
return Visibility;
}
public void setVisibility(String visibility) {
this.Visibility = visibility;
}
public Object getProperty(int index) {
switch (index) {
case 0:
Integer iRecipient = new Integer(idRecipient);
return iRecipient;
case 1:
return txtRealAddress;
case 2:
return Visibility;
default:
return null;
}
}
public int getPropertyCount() {
return 3;
}
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idRecipient";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRealAddress";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Visibility";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
idRecipient = Integer.parseInt(value.toString());
break;
case 1:
txtRealAddress = value.toString();
break;
case 2:
Visibility = value.toString();
break;
default:
break;
}
}
}
The method that sends the request is the following:
TSavedMessage msgTemp = new TSavedMessage();
msgTemp.setSToken(LoginActivity.sToken);
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
msgTemp.setDateDeferredDelivery(dateFormat.format(date));
msgTemp.setIdDepartment(datasource.getDepartmentID(departmentString));
msgTemp.setBDraft(false);
msgTemp.setTxtRelationsType("");
msgTemp.setTxtRelatedIds("");
msgTemp.setIdForwardOf(params[1]);
msgTemp.setIdReplyOf(params[2]);
msgTemp.setNumPriority("Normal");
msgTemp.setBReadReceipt(false);
msgTemp.setBDeliveryReport(false);
msgTemp.setTxtKeywords(keywords.getText().toString());
msgTemp.setNumTimeOffset(0);
msgTemp.setTxtTimeZone("0");
msgTemp.setTxtSubject(subject.getText().toString());
msgTemp.setTxtBody(body.getText().toString());
TRecipient[] recarrayTemp = new TRecipient[1];
recarrayTemp[0] = new TRecipient(0, "nickvoulgaris#hotmail.com", "To");
msgTemp.setRecipients(recarrayTemp);
SoapObject recipients = new SoapObject(LoginActivity.NAMESPACE, "Recipients");
SoapObject recarray[] = new SoapObject[1];
for (int i = 0; i < 1; i++){
recarray[i] = new SoapObject(BaseObject.NAMESPACE, "TRecipient");
recarray[i].addProperty("idRecipient", Integer.toString(0));
recarray[i].addProperty("txtRealAddress", "nickvoulgaris#hotmail.com");
recarray[i].addProperty("Visibility", "To");
recipients.addProperty("TRecipient", recarray[i]);
}
SoapObject msg = new SoapObject(BaseObject.NAMESPACE, "MessageToSend");
msg.addProperty("sToken", LoginActivity.sToken);
msg.addProperty("dateDeferredDelivery", msgTemp.getDateDeferredDelivery());
msg.addProperty("idDepartment", Integer.toString(msgTemp.getIdDepartment()));
msg.addProperty("bDraft", "false");
msg.addProperty("txtRelationsType", Integer.toString(0));
msg.addProperty("txtRelatedIds", Integer.toString(0));
msg.addProperty("idForwardOf", Integer.toString(0));
msg.addProperty("idReplyOf", Integer.toString(0));
msg.addProperty("numPriority", msgTemp.getNumPriority());
msg.addProperty("bReadReceipt", "false");
msg.addProperty("bDeliveryReport", "false");
msg.addProperty("txtKeywords", msgTemp.getTxtKeywords());
msg.addProperty("numTimeOffset", msgTemp.getNumTimeOffset());
msg.addProperty("txtTimeZone", msgTemp.getTxtTimeZone());
msg.addProperty("txtSubject", msgTemp.getTxtSubject());
msg.addProperty("txtBody", msgTemp.getTxtBody());
msg.addProperty("Recipients", recipients);
SoapObject rpc = new SoapObject(BaseObject.NAMESPACE, METHOD_NAME);
rpc.addProperty("sToken", LoginActivity.sToken);
rpc.addProperty("MessageToSend", msg);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
try {
HttpTransportSE androidHttpTransport = new HttpTransportSE(LoginActivity.URL);
androidHttpTransport.debug = true;
androidHttpTransport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
androidHttpTransport.call(SOAP_ACTION, envelope);
System.out.println("=== " + envelope.getResponse().toString());
}
catch(XmlPullParserException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
Finally, the error that I'm getting is this one:
SoapFault - faultcode: 'EConvertError' faultstring: '''0nickvoulgaris#hotmail.comTo'' is not a valid integer value'
faultactor: 'null' detail: null
It is quite unfortunate that the error points me to nowhere. I cannot understand why is trying to pass these 3 fields as an Integer. Also what troubles me is the fact that there is a triple quote in the left hand side and a double one in the right hand side.
Any thoughts could prove extremely valuable. Thanks in advance.
Also, the soap object that this code generates and tries to send seems perfectly ok. It is the following:
MobSaveMessage{
sToken=MOB-2704FB8FFBC946469408A3BEE90CA163;
MessageToSend=MessageToSend{
sToken=MOB-2704FB8FFBC946469408A3BEE90CA163;
dateDeferredDelivery=2012/07/25 13:30:36;
idDepartment=18;
bDraft=false;
txtRelationsType=0;
txtRelatedIds=0;
idForwardOf=0;
idReplyOf=0;
numPriority=Normal;
bReadReceipt=false;
bDeliveryReport=false;
txtKeywords=key;
numTimeOffset=0;
txtTimeZone=0;
txtSubject=sub;
txtBody=mail;
Recipients=Recipients{
TRecipient=TRecipient{
idRecipient=0;
txtRealAddress=nickvoulgaris#hotmail.com;
Visibility=To;
};
};
};
}
After all it turns out that we had a wrong version of the WSDL file sent to us along with the specifications. I'm really sorry if I put anyone into trouble. Not really my fault. I'm just responding in case anyone bumps into the question.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="checkpoint">
<SOAP-ENV:Body>
<ns1:getPedidoResponse xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/">
<tabla xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:pedidos[1]">
<item xsi:type="tns:pedidos">
<ID_PEDIDO xsi:type="xsd:int">1</ID_PEDIDO>
<RUT_CLIENTE xsi:type="xsd:int">1234</RUT_CLIENTE>
<ID_PAQUETE xsi:type="xsd:int">1</ID_PAQUETE>
<RUT_EMPLEADO xsi:type="xsd:int">5678</RUT_EMPLEADO>
<DIRECCION xsi:type="xsd:string">la moenda</DIRECCION>
<LATITUD xsi:type="xsd:string">-33,44291</LATITUD>
<lONGITUD xsi:type="xsd:string">-70,65386</lONGITUD>
<ESTADO xsi:type="xsd:int">1</ESTADO>
</item>
</tabla>
</ns1:getPedidoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And this is my class:
public class Pedidos implements KvmSerializable {
public int ID_PEDIDO;
public int RUT_CLIENTE;
public int ID_PAQUETE;
public int RUT_EMPLEADO;
public String DIRECCION;
public String LATITUD;
public String lONGITUD;
public int ESTADO;
public Pedidos(){}
#Override
public Object getProperty(int arg0) {
switch (arg0){
case 0:
return ID_PEDIDO;
case 1:
return RUT_CLIENTE;
case 2:
return ID_PAQUETE;
case 3:
return RUT_EMPLEADO;
case 4:
return DIRECCION;
case 5:
return LATITUD;
case 6:
return lONGITUD;
case 7:
return ESTADO;
default:
return null;
}
}
#Override
public int getPropertyCount() {
return 7;
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
switch (arg0){
case 0:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ID_PEDIDO";
break;
case 1:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "RUT_CLIENTE";
break;
case 2:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ID_PAQUETE";
break;
case 3:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "RUT_EMPLEADO";
break;
case 4:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "DIRECCION";
break;
case 5:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "LATITUD";
break;
case 6:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "lONGITUD";
break;
case 7:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ESTADO";
break;
default:
break;
}
}
#Override
public void setProperty(int arg0, Object arg1) {
switch(arg0){
case 0:
ID_PEDIDO = Integer.parseInt(arg1.toString());
break;
case 1:
RUT_CLIENTE = Integer.parseInt(arg1.toString());
case 2:
ID_PAQUETE = Integer.parseInt(arg1.toString());
case 3:
RUT_EMPLEADO = Integer.parseInt(arg1.toString());
case 4:
DIRECCION = arg1.toString();
case 5:
LATITUD = arg1.toString();
case 6:
lONGITUD = arg1.toString();
case 7:
ESTADO = Integer.parseInt(arg1.toString());
default:
}
}
}
And here i make the call:
public class MainActivity extends Activity {
static final String SOAP_ACTION="http://192.168.117.1/ws_checkpoint.php/getPedido";
static final String METHOD_NAME="getPedido";
static final String NAMESPACE="checkpoint";
static final String URL="http://192.168.117.1/ws_checkpoint.php";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("pRutEmpleado",5678);
SoapObject result;
HttpTransportSE httpt = new HttpTransportSE(URL);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.addMapping(NAMESPACE, "checkpoint", Pedidos.class);
envelope.dotNet = false;
envelope.bodyOut = request;
try
{
httpt.debug = true;
httpt.call(SOAP_ACTION, envelope);
result = (SoapObject)envelope.bodyIn;
Vector<Pedidos> result_array = (Vector<Pedidos>)envelope.getResponse();
if(result_array != null){
for (Pedidos current_crop: result_array){
System.out.println(current_crop.RUT_EMPLEADO);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The error is :
java.lang.ClassCastException: org.ksoap2.serialization.SoapObject
when i trying to print current_crop.RUT_EMPLEADO.
I think this is due to AndroidHttpTransport, please check this out How to call a .NET Webservice from Android using KSOAP2?
and http://seesharpgears.blogspot.com/2010/11/basic-ksoap-android-tutorial.html
Thank you.
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
I'm currently trying to retrieve an array from my webservice by using regular Ksoap implementation. However, when trying to access this array I am getting the following logcat error:
04-27 00:27:01.772: ERROR/AndroidRuntime(530): Caused by: java.lang.RuntimeException: Unable to
start activity ComponentInfo{android.waiter/android.waiter.TablesActivity}:
java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive
It appears that for some reason Soap is not getting along with the way I am casting my property values. Attached is the problem code (and related methods)
public static TableDTO[] RetrieveFromSoap(SoapObject soap)
{
TableDTO[] tables = new TableDTO[soap.getPropertyCount()];
for (int i = 0; i < tables.length-1; i++) {
SoapObject pii = (SoapObject) soap.getProperty(i);
TableDTO table = new TableDTO();
table.setTableID(Integer.parseInt(pii.getProperty(0).toString()));
table.setCapacity(Integer.parseInt(pii.getProperty(1).toString()));
table.setStatusFlag(pii.getProperty(2).toString());
table.setCurrentWaiter(pii.getProperty(3).toString());
tables[i] = table;
}
return tables;
}
TableDTO Information:
#Override
public Object getProperty(int arg0) {
switch(arg0)
{
case 0:
return TableID;
case 1:
return Capacity;
case 2:
return StatusFlag;
case 3:
return currentWaiter;
}
return null;
}
#Override
public int getPropertyCount() {
// TODO Auto-generated method stub
return 3;
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo info) {
switch(arg0){
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "TableID";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Capacity";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "StatusFlag";
break;
case 3:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "currentWaiter";
break;
default:break;
}
}
#Override
public void setProperty(int arg0, Object value) {
switch(arg0)
{
case 0:
TableID = Integer.parseInt(value.toString());
break;
case 1:
Capacity = Integer.parseInt(value.toString());
break;
case 2:
StatusFlag = value.toString();
break;
case 3:
currentWaiter = value.toString();
break;
default :
break;
}
}
The problem is with the line
SoapObject pii = (SoapObject) soap.getProperty(i);
It does not like the casting there. I'm at a loss on how to fix this.
Thanks for your time and help!
Instead of using
SoapObject response = (SoapObject)envelope.getResponse();
Use
SoapObject response = (SoapObject)envelope.bodyIn;
That worked for me.