在 Android 中从基于 SOAP 的 .NET Web 服务接收自定义对象
我正在开发一个 Android 应用程序,它需要连接到 .NET SOAP Web 服务并从响应中生成/填充许多对象。我对 Web 服务和 SOAP 完全陌生,对 Android 也比较陌生。 Web 服务已经构建(不是我构建的)。
我一直在尝试查找有关在 Android 中连接 SOAP Web 服务的信息。两个基本建议似乎是:
- 不要使用 SOAP,
- 如果使用 SOAP,请使用 KSOAP2。
我看过 KSOAP2 的各种教程,但它们似乎都只处理最基本的原始类型,例如发送 2 个整数以获取 1 个整数,或者发送和接收字符串;但是,我需要发送自定义对象来回。
是否可以使用 KSOAP2 发送和接收自定义对象?如果是这样,这有多容易/困难?是否必须解析 XML 才能“手动”创建/填充对象?
编辑/更新: 在尝试连接到现有的 Web 服务一段时间(接受一个字符串并返回一个复杂的对象)并收到错误后,我决定尝试一种更简单的方法。我连接到一个更简单的 Web 服务,它不带任何参数,并返回一个 int。这个更简单的 Web 服务托管在与原始 Web 服务相同的位置,现在这个简单的 Web 服务对我来说工作得很好。
进一步更新: 现在一切正常!结果我只是遇到了一个大小写错误,导致我的参数丢失。
最后的问题是“国家”与“国家”。这是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);
我想我在传递对象作为参数时添加了Marshal部分,我不确定我是否还需要它们。我也不确定 addMapping 调用,以及我应该在其中包含什么。谢谢。
I'm developing an Android app which needs to connect to a .NET SOAP web service and generate/populate a number of objects from the response. I'm totally new to web services and SOAP, and relatively new to Android. The web service has already been built (not by me).
I've been trying to find info on connecting to SOAP web services in Android. The two basic suggestions seem to be:
- Don't use SOAP,
- If you do use SOAP, use KSOAP2.
I've looked at various tutorials for KSOAP2 but they all seem to deal only with the most basic, primitive types, such as sending 2 ints to get 1 int back, or sending and receiving strings;, however, I need to send custom objects back and forth.
Is it possible to send and receive custom objects using KSOAP2? If so, how easy/difficult is this? Does the XML have to be parsed to create/populate the objects "by hand"?
EDIT/UPDATE:
After trying for a while to connect to the existing webservice (takes a String and returns a complex object), and getting an error, I decided to try a simpler approach. I connected to a simpler webservice which takes no parameters, and returns an int. This simpler webservice is hosted in the same place as the original one, and the simple one now works fine for me.
FURTHER UPDATE:
All working fine now! Turns out I just had a capitalisation error which was throwing off my parameter.
The final problem was "national" versus "National". Here's the soapUI-generated code:
<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>
And the request code which was being generated by my 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>
My final java code is:
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);
}
}
I am still confused about these lines:
envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().
Marshal floatMarshal = new MarshalFloat();
floatMarshal.register(envelope);
I think I added the Marshal parts when I was passing an object as a parameter, I'm not sure if I still need them. I'm also not sure about the addMapping call either, and what I should have in there. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 ksoap2,并在以下链接中通过代码示例检查我的答案:链接1,链接2,链接3。我写了一些详细信息,将帮助您了解如何开始编码。
如果您需要帮助,请告诉我。
更新(回答有关映射和编组的问题)
当您通过soap信封发送复杂类型(即对象)时,请使用addMapping。 Web服务如何识别复杂类型?您需要在本地创建一个实现 kvmserialized 的类(如我的链接中提到的),该类将具有与服务器上的对象相同的参数,然后您需要在它和映射的类之间添加映射到服务器上,以便在服务器上解析信封时,它知道此复杂类型 X 映射到服务器上的类 X 。因此,如果您不发送复杂类型,则不需要添加映射。(PS:我看到您没有发送复杂类型,因为NationalID是字符串类型。如果可以说NationalID是复杂类型Z 你会这样做:addMapping(NAMESPACE, Z.class.getSimpleName(), Z.class) )
至于编组,它使用java序列化将对象更改为数据流在网络服务上解组。因此,当您发送复杂类型时,根据我的经验,添加编组以通过序列化将复杂类型更改为数据流是一个很好的做法。如果您发现不需要它,请不要添加它,但了解有哪些选项总是有好处的。
Use ksoap2, and check my answers with code examples at the following links: Link1,link2,link3. I wrote some details which will help you understand how to start coding.
let me know if u need help.
UPDATE ( Answering your question about mapping and marshalling)
u use addMapping when you are Sending a complex type ( ie an object) through the soap envelope. How will the webservice recognize the complex type ? u need to create locally a class that implement kvmserializable (as mentionned in my links) which will have same parameter as the object on the server, and then u need to add mapping between it and the class that maps to it on the server, so that the enveloppe when parsed on the server it knows this complex type X map to class X on the server. So if you are not Sending complex type, you don't need to add mapping.(PS:I see that your not sending a complex type since nationalID is of type string. IF lets say nationalID was a complex type of type Z you would do : addMapping(NAMESPACE, Z.class.getSimpleName(), Z.class) )
As for marshalling, it uses java serialization to change Objects to stream of data to be unmarshalled on the web service. So when u are sending a complex type,based on my experience, it is a good practice to add marshalling to change the complex type to streams of data by serializing it. If you find that you don't need it just don't add it, but its always good to understand what are the options out there.
看看这个http://seesharpgears.blogspot。 com/2010/10/ksoap-android-web-service-tutorial-with.html,有如何传递复杂对象的示例。
Look at this http://seesharpgears.blogspot.com/2010/10/ksoap-android-web-service-tutorial-with.html , there are examples of how to pass complex objects.