在Android中从基于SOAP的.NET Web服务接收自定义对象

时间:2012-02-03 15:19:06

标签: android .net web-services soap ksoap2

我正在开发一个Android应用程序,它需要连接到.NET SOAP Web服务并从响应中生成/填充许多对象。我对Web服务和SOAP都很陌生,而且对Android来说相对较新。 Web服务已经构建(不是由我)。

我一直在尝试查找有关在Android中连接到SOAP Web服务的信息。这两个基本建议似乎是:

  1. 不要使用SOAP,
  2. 如果您使用SOAP,请使用KSOAP2。
  3. 我已经查看了KSOAP2的各种教程,但它们似乎只处理最基本的原始类型,例如发送2个int以获得1个int,或者发送和接收字符串;但是,我需要来回发送自定义对象。

    是否可以使用KSOAP2发送和接收自定义对象?如果是这样,这有多容易/困难?是否必须解析XML以手动创建/填充对象"?

    修改/更新: 在尝试连接到现有的webservice(接受一个String并返回一个复杂的对象)并获得错误之后,我决定尝试一种更简单的方法。我连接到一个不带参数的简单web服务,并返回一个int。这个更简单的Web服务托管在与原始Web服务相同的位置,简单的Web服务现在可以正常使用。

    进一步更新: 一切正常!事实证明我只是有一个大写错误,它抛弃了我的参数。

    最后一个问题是"国家"与#34;国家"。这是soapUI生成的代码:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     xmlns:tem="http://tempuri.org/">
       <soapenv:Header/>
       <soapenv:Body>
          <tem:GetClientByNationalID>
             <!--Optional:-->
             <tem:nationalID>XXXXXXX</tem:nationalID>
          </tem:GetClientByNationalID>
       </soapenv:Body>
    </soapenv:Envelope>
    

    我的Java生成的请求代码:

    <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>
            <GetClientByNationalID xmlns="http://tempuri.org/" id="o0" c:root="1">
                <NationalID i:type="d:string">
                    XXXXXXXX
                </NationalID>
            </GetClientByNationalID>
        </v:Body>
    </v:Envelope>
    

    我的最终java代码是:

    public void webServiceCall() {
        String NAMESPACE = "http://tempuri.org/";
        String METHOD_NAME = "GetClientByNationalID";
        String SOAP_ACTION = "http://tempuri.org/IClientService/GetClientByNationalID"; 
    
        // unsecure service
        String URL = "http://XXXXXXXXXXXXXXXXXXXX.net/FPUnSecureService/ClientService.svc";
    
        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 
    
        String clientID = "XXXXXXX";
    
        PropertyInfo pi = new PropertyInfo();
        pi.setName("nationalID"); 
        pi.setValue(clientID); 
        pi.setType(clientID.getClass()); 
        request.addProperty(pi);
    
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
        envelope.dotNet = true;
        envelope.setOutputSoapObject(request); 
    
        envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().getClass());
        Marshal floatMarshal = new MarshalFloat();
        floatMarshal.register(envelope);
    
        HttpTransportSE t = new HttpTransportSE(URL); 
    
        ClientID client = new ClientID(); 
        t.debug = true; 
    
        try { 
            Log.i("webServiceCall", "Trying call to web service");
            t.call(SOAP_ACTION, envelope);
            SoapObject response = (SoapObject) envelope.getResponse();
    
            Log.i("success", response.getPropertyAsString(0)); 
            Log.i("success", response.getPropertyAsString(1));
            Log.i("success", response.getPropertyAsString(2));
            Log.i("success", response.getPropertyAsString(3));
            Log.i("success", response.getPropertyAsString(4)); 
    
        } catch (Exception e) {
            Log.e("webServiceCall", "Error calling webservice.");
            e.printStackTrace(); 
            System.out.println("Request: "  + t.requestDump); 
            System.out.println("Response: " + t.responseDump);
        }
    
    }
    

    我仍然对这些问题感到困惑:

    envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().
    Marshal floatMarshal = new MarshalFloat();
    floatMarshal.register(envelope);
    

    我认为当我将一个物体作为参数传递时,我添加了元帅部分,我不确定我是否还需要它们。我也不确定addMapping调用,以及我应该拥有的内容。谢谢。

2 个答案:

答案 0 :(得分:1)

使用kso​​ap2,并通过以下链接使用代码示例检查我的答案:Link1link2link3。我写了一些细节,可以帮助您了解如何开始编码。
如果你需要帮助,请告诉我。

更新(回答有关映射和编组的问题)
当您通过soap信封发送复杂类型(即对象)时,请使用addMapping。 Web服务如何识别复杂类型?你需要在本地创建一个实现kvmserializable的类(在我的链接中提到),它将与服务器上的对象具有相同的参数,然后你需要在它和映射的类之间添加映射在服务器上对它进行处理,以便在服务器上解析时,它知道服务器上的这个复杂类型 X 映射到类 X 。因此,如果您不是发送复杂类型,则不需要添加映射。( PS:我发现您没有发送复杂类型,因为nationalID是string类型.IF可以说nationalID是一种复杂类型 Z 你会这样做:addMapping(NAMESPACE,Z.class.getSimpleName(),Z.class)

对于编组,它使用java序列化将对象更改为要在Web服务上解组的数据流。因此,当您发送复杂类型时,根据我的经验,添加编组以通过序列化将复杂类型更改为数据流是一种很好的做法。如果你发现你不需要它只是不添加它,但它总是很好理解那里的选项。

答案 1 :(得分:0)

看看这个http://seesharpgears.blogspot.com/2010/10/ksoap-android-web-service-tutorial-with.html,有一些如何传递复杂对象的例子。