سؤال

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??

EDIT

Also, 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;
        }
    }
}

EDIT 1

So on my 2nd problem the issue was the ordering of the properties. Using SoapUI as suggested showed me the layout of the properties as expected by my server. I need to do this instead of what I had above.

test1.addProperty("Name", "Test");
test1.addProperty("ID", 1);
test1.addProperty("UserID", 1);
هل كانت مفيدة؟

المحلول

Set the right namespace of parameters, i.e:

 PropertyInfo propertyInfo = new PropertyInfo();
 propertyInfo.setNamespace("http://schemas.datacontract.org/2004/07/MyDataNamespace.Data");
 propertyInfo.setName("ID");
 propertyInfo.setValue("1");
 test1.addProperty(propertyInfo);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top