понедельник, мая 28, 2012

Как передать массив из Android в WCF?

Ну, то что из Android практически невозможно передать сложный тип веб-сервису на WCF, понятно. Ведь кроме Microsoft для Microsoft ничего не существует. Тут даже и вопросов никаких не возникает: "так надо". А вот почему нужны такие пляски с бубнами для передачи простого массива из приложения на Android в WCF-сервис, непонятно. Этот ваш любимый ksoap2 тоже не особо-то помогает в виде "из коробки". Приходится смотреть логи, сравнивать сообщения и подстраиваться. А что, замечательный способ разработки. Если некуда спешить.

Короче.

Полностью завершённый код C#, делающий то, что нужно
class Program
{
 static void Main(string[] args)
 {
  ServiceReference1.ServiceClient sr = new ServiceReference1.ServiceClien();
  sr.GetSomething(new []{10, 20, 30});
  sr.Close();
 }
}
Вызывает и работает.

Теперь то же самое из Android. Просто так передать массив не получится, его надо передавать изощрённо (извращённо?). Потому что в противном случае WCF не сможет десериализовать сообщение.

Делай раз
1. Сделать вид, что передаём не какой-то там паршивый int[], но настоящий Объект! настоящего Класса! Со всеми атрибутами такого. А именно
2. Полный код "взрослого класса"
public class MyIds extends Vector implements KvmSerializable {
    private static final long serialVersionUID = -1143242342342342265L;

    @Override
    public Object getProperty(int i) {
        return this.get(i);
    }
    @Override
    public int getPropertyCount() {
        return this.size();
    }
    @Override
    public void setProperty(int i, Object o) {
        this.add(Integer.parseInt(o.toString()));
    }
    @Override
    public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
        propertyInfo.name = "int";
        propertyInfo.namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";        propertyInfo.type = PropertyInfo.INTEGER_CLASS;
    }
}

Самый цимес в жирной строчке. Хотите неприятно провести время - уберите её.

После этого вызов метода GetSomething в Android становится очень простым
3. public static int getSomething(int[] args)
    {
        final String MethodName = "GetSomething";
        final String SoapAction = "http://mydomain.ru/MyService/IInterface/GetSomething";
        SoapObject req = new SoapObject(Namespace, MethodName);

        MyIds myIds = new MyIds();
        for(Integer i : args)
            myIds.add(i);
       
        PropertyInfo pi = new PropertyInfo();
        pi.setName("WCFParam");
        pi.setValue(myIds);
        pi.setType(myIds.getClass());
        req.addProperty(pi);
        SoapSerializationEnvelope se = getEnvelope(req);
        SoapPrimitive p = initializeTransportAndCall(SoapAction, se);

        if (null == p)
            return 0;

        return Integer.parseInt(p.toString());
    }
Всё. WCF SOAP WS принимает массив целых чисел. Ну и дальше дело техники.

Комментариев нет: