从android客户端向wcf服务发送复杂类型时,服务器收到null

时间:2012-02-20 12:05:21

标签: android wcf ksoap2

我正在使用kso​​ap2库连接到wcf Web服务。当我尝试发送原始类型时,服务器获取这些值并发送正确的响应。但是,如果我尝试发送一个复杂类型(一个KVMSerilizable子类型的对象),服务器将收到null。 下面是我要发送的对象的类定义。

import java.util.Hashtable;

import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;

public class TwoIntegerWrapper implements KvmSerializable {

    private int Num1;
    private int Num2;

    public TwoIntegerWrapper() {
        super();
    }

    TwoIntegerWrapper(int number1, int number2) {
        super();
        this.Num1 = number1;
        this.Num2 = number2;
    }

    public int getNumber1() {
        return Num1;
    }

    public void setNumber1(int number1) {
        this.Num1 = number1;
    }

    public int getNumber2() {
        return Num2;
    }

    public void setNumber2(int number2) {
        this.Num2 = number2;
    }

    public Object getProperty(int propertyNumber) {

        Object property = null;

        switch (propertyNumber) {
        case 0:
            property = this.Num1;
            break;

        case 1:
            property = this.Num2;
            break;

        }

        return property;
    }

    public int getPropertyCount() {
        return 2;
    }

    public void getPropertyInfo(int propertyNumber, Hashtable arg1,
            PropertyInfo propertyInfo) {

        switch (propertyNumber) {
        case 0:
            propertyInfo.type = PropertyInfo.INTEGER_CLASS;
            propertyInfo.name = "Num1";
            break;
        case 1:
            propertyInfo.type = PropertyInfo.INTEGER_CLASS;
            propertyInfo.name = "Num2";
            break;
        }

    }

    public void setProperty(int propertyNumber, Object data) {
        switch (propertyNumber) {

        case 0:
            this.Num1 = Integer.parseInt(data.toString());
            break;
        case 1:
            this.Num2 = Integer.parseInt(data.toString());
            break;
        }

    }
}

以下是我称之为网络服务的方式。

SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

PropertyInfo property = new PropertyInfo();
TwoIntegerWrapper tiw = new TwoIntegerWrapper(num1Value, num2Value);

property.setName("TwoIntegerWrapper");
property.setType(tiw.getClass());
property.setValue(tiw);

request.addProperty(property);

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);

envelope.addMapping(NAMESPACE, tiw.getClass().getSimpleName(), TwoIntegerWrapper.class);

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

try {
    androidHttpTransport.call(Add_SOAP_ACTION, envelope);

    Log.d(logtag + " request dump", androidHttpTransport.requestDump);
    Log.d(logtag + " response dump", androidHttpTransport.responseDump);


   SoapPrimitive sp = (SoapPrimitive) envelope.getResponse();
   result = Integer.parseInt(sp.toString());
}

可能的原因是什么?

4 个答案:

答案 0 :(得分:1)

这方面的一个常见问题是,假设您在线路上发送XML,则XML位于错误的命名空间中。在这种情况下,WCF解串器将决定它在XML中没有任何知道并返回null

答案 1 :(得分:0)

我建议使用Fiddler检查请求和响应。

在WCF服务上启用Tracing,并通过检查跟踪文件来查看通道上显示的消息。

答案 2 :(得分:0)

你的实现kvmserializable的类是基于 xsd2 准确的。 但是, AddNumbers2,AddNumbers3 的方法(消息)具有第一个AN ELEMENT,它具有元素类型复杂类型,例如:

 <xs:element name="AddNumbers2">
  <xs:complexType>
    <xs:sequence>
      <xs:element minOccurs="0" name="obj" nillable="true" type="q1:TwoIntegerWrapper"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

所以你应该做的是:

property.setName("AddNumbers2");//not TwoIntegerWrapper, coz the main property is AddNumbers2
property.setType(tiw.getClass());
property.setValue(tiw);
request.addProperty(property);

答案 3 :(得分:0)

我通过更改 TwoIntegerWrapper 类的 getPropertyInfo 函数找到了解决方案。我还为这个类中的每个属性设置了名称空间。新的实施如下:

public void getPropertyInfo(int propertyNumber, Hashtable arg1,
        PropertyInfo propertyInfo) {

    switch (propertyNumber) {
    case 0:
        propertyInfo.type = PropertyInfo.INTEGER_CLASS;
        propertyInfo.name = "Num1";
        propertyInfo.setNamespace(TWO_INTEGER_WRAPPER_NAMESPACE);
        break;
    case 1:
        propertyInfo.type = PropertyInfo.INTEGER_CLASS;
        propertyInfo.name = "Num2";
        propertyInfo.setNamespace(TWO_INTEGER_WRAPPER_NAMESPACE);
        break;
    }

}

即使我从信封中删除了映射,它也能正常工作。我不明白为什么会这样,但它确实有效。如果有人解释原因我很感激。 Wsdl文件,xsd0,xsd1和xsd2文件位于链接http://www.ceng.metu.edu.tr/~e1559897/

顺便说一句,我也改变了

property.setName("TwoIntegerWrapper");  

property.setName("obj");