Search code examples
androidarrayswcfksoap2

ksoap2 Sending array of complex objects to WCF service


I'm trying to send an array of complex objects from android client to my WCF service. I used http://seesharpgears.blogspot.ru/2010/10/web-service-that-returns-array-of.html as an example for receiving an array of complex objects and that works fine. But I can't understand how to send this array.

I'm using kmvserializable for object: public class RatingHttps implements KvmSerializable {

public int CIsso;

public int RatingIsso;

public long RatingDate;

public String RatingExt;

public RatingHttps() {super();}

public RatingHttps(int CIsso, int RatingIsso, long RatingDate, String RatingExt) {
    this.CIsso = CIsso;
    this.RatingIsso = RatingIsso;
    this.RatingDate = RatingDate;
    this.RatingExt = RatingExt;
}

@Override
public Object getProperty(int i) {
    Object property = null;
    switch (i) {
        case 0:
            property = this.CIsso;
            break;
        case 1:
            property = this.RatingDate;
            break;
        case 2:
            property = this.RatingExt;
            break;
        case 3:
            property = this.RatingIsso;
            break;
    }
    return property;
}

@Override
public int getPropertyCount() {
    return 4;
}

@Override
public void setProperty(int i, Object o) {
    switch (i) {
        case 0:
            this.CIsso = Integer.parseInt(o.toString());
            break;
        case 1:
            this.RatingDate = Long.parseLong(o.toString());
            break;
        case 2:
            this.RatingExt = o.toString();
            break;
        case 3:
            this.RatingIsso = Integer.parseInt(o.toString());
            break;

    }
}
private static final String NAMESPACE = "http://schemas.datacontract.org/2004/07/Ais7UpdateServer";

@Override
public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
    switch (i) {
        case 0:
            propertyInfo.type = PropertyInfo.INTEGER_CLASS;
            propertyInfo.name = "CIsso";
            propertyInfo.setNamespace(NAMESPACE);
            break;
        case 1:
            propertyInfo.type = PropertyInfo.LONG_CLASS;
            propertyInfo.name = "RatingDate";
            propertyInfo.setNamespace(NAMESPACE);
            break;
        case 2:
            propertyInfo.type = PropertyInfo.STRING_CLASS;
            propertyInfo.name = "RatingExt";
            propertyInfo.setNamespace(NAMESPACE);
            break;
        case 3:
            propertyInfo.type = PropertyInfo.INTEGER_CLASS;
            propertyInfo.name = "RatingIsso";
            propertyInfo.setNamespace(NAMESPACE);
            break;
        default: break;
    }
}

This is how I use it:

List<RatingHttps> ratings = new ArrayList<>();
        RatingHttps rating = new RatingHttps();
        rating.CIsso = 1;
        rating.RatingIsso = 2;
        rating.RatingExt = "LOL";
        rating.RatingDate = 3;
        ratings.add(rating);
        rating = new RatingHttps();
        rating.CIsso = 10;
        rating.RatingIsso = 20;
        rating.RatingExt = "OLOLO";
        rating.RatingDate = 30;
        ratings.add(rating);
            //cr.moveToNext();


        //request = GetSoapObject(METHOD_NAME[2]);
        request = new SoapObject(NAMESPACE, METHOD_NAME[2]);

        //envelope = GetEnvelope(request);
        request.addProperty("id", resultId.toString());
        //PropertyInfo pi = new PropertyInfo();
        //pi.setName("ratings");
        //pi.setValue(ratings);
        //pi.setType(ratings.getClass());

        //request.addProperty(pi);
        request.addProperty("ratings", ratings);

        //envelope.addMapping(NAMESPACE, ratings.getClass().getSimpleName(), ratings.getClass());
        envelope.addMapping(NAMESPACE, "ArrayOfRatingHttps", RatingHttps.class);
        SoapObject count = (SoapObject) SecureConnect(SOAP_ACTION[2], request, envelope);

SecureConnect:

private Object SecureConnect(String soapAction, SoapObject request, SoapSerializationEnvelope envelope) {
    try {
        if(request != null) {
            envelope.setOutputSoapObject(request);
            envelope.dotNet = true;
        }
        HttpsTransportSE androidHttpsTransport = new HttpsTransportSE(host, port, subFile, 20000);
        androidHttpsTransport.call(soapAction, envelope);
        return envelope.getResponse();
    } catch (Exception e) {
        result = e.toString();
        Log.d("Tag", "Ошибка: " + e.toString());
        return null;
    }
}

I tried with Arrays, like Rating[].. And with Vector, but this won't work. I don't know what to do! Maybe anyone has some examples how to do it? Please help.


Solution

  • After many hours of searching through the Internet, I've finally found working example. If you would have the same problem, please make sure, that you send correct xml file. Firstly I matched xml file, that I had to receive, with xml file on server. When I found out, that they were the same, I found a mistake in tags, and I'll show how I did it in code: My RatingHttps class is the same as in my question; Init my class for example:

    List<RatingHttps> rating = new ArrayList<>();
            RatingHttps ratings = new RatingHttps();
            ratings.CIsso = 1;
            ratings.RatingIsso = 2;
            ratings.RatingExt = "LOL";
            ratings.RatingDate = 3;
            rating.add(ratings);
    

    Next, the request:

    request = new SoapObject(NAMESPACE, METHOD_NAME[2]);
            SoapObject ratingRequest = new SoapObject(NAMESPACE, "ArrayOfRatingHttps");
            request.addProperty("id", resultId.toString());
            PropertyInfo pi = new PropertyInfo();
            pi.setName("ratings");
            pi.setValue(ratingRequest);
            pi.setType("ArrayOfRatingHttps");
            request.addProperty(pi);
    
            for(int i = 0; i < rating.size(); i++) {
                SoapObject rate = new SoapObject(RatingHttps.NAMESPACE, RatingHttps.class.getSimpleName());
    
                //Добавляем значения RatingHttps в xml запрос
                rate.addProperty(getPropInfo(rating.get(i).getAttributeName(0), rating.get(i), rating.get(i).getAttributeType(0)));
                rate.addProperty(getPropInfo(rating.get(i).getAttributeName(1), rating.get(i), rating.get(i).getAttributeType(1)));
                rate.addProperty(getPropInfo(rating.get(i).getAttributeName(2), rating.get(i), rating.get(i).getAttributeType(2)));
                rate.addProperty(getPropInfo(rating.get(i).getAttributeName(3), rating.get(i), rating.get(i).getAttributeType(3)));
    
                ratingRequest.addSoapObject(rate);
            }
            envelope.addMapping(NAMESPACE, RatingHttps.class.getSimpleName(), RatingHttps.class);
    HttpsTransportSE androidHttpsTransport = new HttpsTransportSE(host, port, subFile, 20000);
            androidHttpsTransport.call(soapAction, envelope);
    

    where "ArrayOfRatingHttps" I found for array in my xsd file. If you have wcf service, you can find it in you address "https://your_address?xsd=xsd2". Also I realized a function getPropInfo, here is the code:

    private PropertyInfo getPropInfo(String name, RatingHttps rating, Object type) {
        PropertyInfo pi = new PropertyInfo();
        pi.setName(name);
        pi.setValue(rating.getCIsso());
        pi.setType(type);
        pi.setNamespace(RatingHttps.NAMESPACE);
        return pi;
    }
    

    where NAMESPACE I found also in xsd file for my service as a targetNamespace. so that's it, now I can send an Array of complex objects. Hope it will help somebody oneday...