Сервер получает пустое значение при отправке сложного типа с Android-клиента в службу wcf - PullRequest
1 голос
/ 20 февраля 2012

Я использую библиотеку ksoap2 для подключения к веб-сервису wcf.Когда я пытаюсь отправить примитивные типы, сервер получает эти значения и отправляет правильный ответ.Однако, если я пытаюсь отправить сложный тип (объект, который является подтипом KVMSerilizable), сервер получает нулевое значение.Ниже приведено определение класса объекта, который я хочу отправить.

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 ]

1 голос
/ 20 февраля 2012

Одна из распространенных проблем заключается в том, что, если вы отправляете XML по проводам, он находится в неверном пространстве имен.В этом случае десериализатор WCF решит, что ничего не знает в XML, и вернет null

0 голосов
/ 27 февраля 2012

Я нашел решение, изменив getPropertyInfo функцию TwoIntegerWrapper класса. Я также установил пространства имен для каждого свойства в этом классе. Новая реализация выглядит следующим образом:

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");  
0 голосов
/ 22 февраля 2012

ок, ваш класс, который реализует kvmserializable, точен на основе xsd2 . Однако методы ( message ), которые вы используете для AddNumbers2, AddNumbers3 , имеют первый элемент 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);
0 голосов
/ 20 февраля 2012

Я бы посоветовал проверить запрос и восстановить его с помощью Fiddler .

Включите Трассировка в вашей службе WCF и посмотрите, какое сообщение появляется на канале, проверив файлы трассировки.

...