launk / ksoap2-android

Automatically exported from code.google.com/p/ksoap2-android
0 stars 0 forks source link

ksoap doesn't seem to be prefixing custom objects with the correct namespace. #172

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Create .NET WCF basicHttpBinding service
2. Create Android application using ksoap
3. Call a method with a custom object on the WCF service.

What is the expected output? What do you see instead?
The custom object makes it to the server. Instead the custom object gets all of 
its values stripped from it, but makes it to the server.

What version of the product are you using? On what operating system?
ksoap2-android-assembly-3.0.0-RC.4-jar-with-dependencies.jar

Please provide any additional information below.
I am trying to send a custom object to my WCF service via ksoap on Android. I 
have the following code below.

String METHOD_NAME = "MyMethod";
String INTERFACE = "IMyInterface";
String NAMESPACE = "http://tempuri.org/";
String SOAP_ACTION = NAMESPACE + INTERFACE + "/" + METHOD_NAME; 

request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("APIKey", API_KEY);
request.addProperty("AuthToken",  AuthToken);
request.addProperty("UserID", 1);

SoapObject test1 = new SoapObject(DATA_NAMESPACE, "MyCustomObject");
test1.addProperty("ID", 1);
test1.addProperty("UserID", 1);
test1.addProperty("Name", "Test");
request.addSoapObject(test1);

SoapSerializationEnvelope envelope = new 
SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.addMapping(DATA_NAMESPACE, "MyCustomObject", new 
MyCustomObject().getClass());
envelope.setOutputSoapObject(request);

HttpTransportSE httpTransport = new HttpTransportSE(URL);
httpTransport.debug = true;

int id = 0;
try {
    httpTransport.call(SOAP_ACTION, envelope);
    SoapPrimitive result = (SoapPrimitive)envelope.getResponse();
    id = Integer.parseInt(result.toString());
} catch (Exception e) {
    String requestDump = httpTransport.requestDump;
    String responseDump = httpTransport.responseDump;
    throw e;
}
I know that the call is actually making it to the web server. Values from 
APIKey, AuthToken, & UserID all make it there successfully. However, in the 
MyCustomObject none of the values make it there. The object does but it has 
been stripped of the values.

I took a look at the requestDump and I found the following.

<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>
<MyMethod xmlns="http://tempuri.org/" id="o0" c:root="1">
  <APIKey i:type="d:string">MyAPIKey</APIKey>
  <AuthToken i:type="d:string">MyAuthToken</AuthToken>
  <UserID i:type="d:int">1</UserID>
  <MyCustomObject i:type="n0:MyCustomObject" xmlns:n0="http://schemas.datacontract.org/2004/07/MyDataNamespace.Data">
    <ID i:type="d:int">1</ID>
    <UserID i:type="d:int">1</UserID>
    <Name i:type="d:string">Test</Name>
  </MyCustomObject>
</MyMethod>
</v:Body>
</v:Envelope>
I then constructed a quick little .net console client and performed the exact 
same action. However, I analyzed the requestDump from the .net client and got 
the following.

{<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IMyInterface/MyMethod</Action>
  </s:Header>
  <s:Body>
    <MyMethod xmlns="http://tempuri.org/">
      <APIKey>MyAPIKey</APIKey>
      <AuthToken>MyAuthToken</AuthToken>
      <UserID>1</UserID>
      <MyCustomObject xmlns:d4p1="http://schemas.datacontract.org/2004/07/MyDataNamespace.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <d4p1:Name>Test</d4p1:Name>
        <d4p1:ID>1</d4p1:ID>
        <d4p1:UserID>1</d4p1:UserID>
      </MyCustomObject>
    </MyMethod>
  </s:Body>
</s:Envelope>}
Now given those pieces and the comparison between XML the only thing I notice 
is that the MyCustomObject's properties are prefixed with the namespace prefix 
d4p1. On the java client the properties are not prefixed with n0 like they 
should be. This would tell me that this is the disconnect and why the object is 
getting its properties stripped. Now the question is how do I tell ksoap to add 
that namespace prefix to the document??

Original issue reported on code.google.com by combsmst...@gmail.com on 8 Oct 2013 at 2:20

GoogleCodeExporter commented 9 years ago
Here is my class that implements KVMSerializable.

    public class MyCustomObject implements KvmSerializable {
        public int ID;
        public int UserID;
        public String Name;

        public MyCustomObject() { }

        public String getName() { return Name; }
        public int getID() { return ID; }
        public int getUserID() { return UserID; }
        public void setName(String name) { Name = name; }
        public void setID(int ID) { ID = ID; }
        public void setUserID(int userID) { UserID = userID; }

        public Object getProperty(int index) {
            switch (index) {
                case 0: return ID;
                case 1: return UserID;
                case 2: return Name;
            }
            return null;
        }

        public void setProperty(int index, Object value) {
            switch (index) {
                case 0: ID = Integer.parseInt(value.toString()); break;
                case 1: UserID = Integer.parseInt(value.toString()); break;
                case 2: Name = value.toString(); break;
            }
        }

        public int getPropertyCount() { return 3; }

        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.INTEGER_CLASS;
                    info.name = "UserID";
                    break;
                case 2:
                    info.type = PropertyInfo.STRING_CLASS;
                    info.name = "Name";
                    break;
            }
        }
    }

Original comment by combsmst...@gmail.com on 8 Oct 2013 at 2:24