Создание SOAP-запроса с помощью KSOAP Android
Мне нужно сгенерировать запрос на мыло, как этот.
SOAP-ЗАПРОС
POST /TennisMasters/TennisMasters.Listener.asmx HTTP/1.1
Host: playinkstudio.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://playinktennismasters.com/authenticateUser"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<authenticateUser xmlns="http://playinktennismasters.com/">
<user>string</user>
</authenticateUser>
</soap:Body>
</soap:Envelope>
Я использую KSOAP2, чтобы построить этот запрос.
private static String SOAP_ACTION = "http://playinktennismasters.com/authenticateUser";
private static String NAMESPACE = "http://playinktennismasters.com/";
private static String METHOD_NAME = "authenticateUser";
private static String URL = "http://playinkstudio.com/TennisMasters/TennisMasters.Listener.asmx";
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("user", "A Json String will be here");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER12);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
} catch (Exception e) {
e.printStackTrace();
}
Это запрос, который я получил от отладки.
<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://www.w3.org/2003/05/soap-encoding" xmlns:v="http://www.w3.org/2003/05/soap-envelope">
<v:Header />
<v:Body>
<authenticateUser xmlns="http://playinktennismasters.com/" **id="o0" c:root="1"**>
<user **i:type="d:string"**>{"email":"asad.mahmood@gmail.com","UserDate":"Feb 22, 2012 7:01:24 PM","GearId":0,"GearValue":0,"Income":0,"Level":0,"MatchResult":0,"MatchType":0,"OfferId":0,"OpponentId":0,"Partners":0,"ExhibitionCount":0,"PowerRuns":0,"PowerServes":0,"PowerShots":0,"Seeds":0,"Energy":0,"Cash":0,"Stamina":0,"Strength":0,"SubLevel":0,"TotalEnergy":0,"TotalStamina":0,"TrainingId":0,"Agility":0,"UserId":0,"Age":0,"ActivityId":0,"gearIsGift":0}</user>
</authenticateUser>
</v:Body>
</v:Envelope>
Я не знаю, почему дополнительные атрибуты, такие как "id" и "c:root", добавляются в authenticateUser. и дополнительный атрибут в i:type="d:String". Пожалуйста, можете прийти кто-нибудь дать мне хороший пример или учебник, который может помочь мне создать запрос, как указано выше, очень нужна помощь, спасибо.
4 ответа
Наконец-то начал работать с KSOAP. Вот код, который я использовал, может быть, он кому-нибудь поможет.
final SoapObject request = new SoapObject(AppConsts.NAMESPACE,
usecaseString);
request.addProperty(addPropertyString, propertyJsonString);
final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
final HttpTransportSE androidHttpTransport = new HttpTransportSE(
AppConsts.URL);
androidHttpTransport.debug = true;
String soapAction = AppConsts.NAMESPACE + usecaseString;
try {
androidHttpTransport.call(soapAction, envelope);
SoapPrimitive resultSoapPrimitive;
resultSoapPrimitive = (SoapPrimitive) envelope.getResponse();
if (resultSoapPrimitive != null) {
result = resultSoapPrimitive.toString();
if (AppConsts.ENABLE_LOG)
Log.d(AppConsts.GAME_TITLE, "result json : " + result);
} else {
if (AppConsts.ENABLE_LOG)
Log.d(AppConsts.GAME_TITLE, "result json is NULL!!! ");
}
} catch (Exception e) {
e.printStackTrace();
Log.e("static", "Exception in making call to server");
}
Для создания вышеуказанного запроса эти три параметра нам нужно передать в код.
AppConsts.NAMESPACE = "http://playinktennismasters.com"
usecaseString = "authenticateUser"
addPropertyString = "user"
Я использовал простые HttpClient и Httppost, Simple String для запроса Envelope.
String temp = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<soap:Body>"
+ "<authenticateUser xmlns=\"http://playinktennismasters.com/\">"
+ "<user>%s</user>" + "</authenticateUser>" + "</soap:Body>"
+ "</soap:Envelope>";
ENVELOPE = String.format(temp, user);
Теперь с помощью метода, который создаст оставшиеся параметры после запроса и вернет строку ответа.
public String CallWebService(String url, String soapAction, String envelope) {
final DefaultHttpClient httpClient = new DefaultHttpClient();
// request parameters
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 15000);
// set parameter
HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), true);
// POST the envelope
HttpPost httppost = new HttpPost(url);
// add headers
httppost.setHeader("soapaction", soapAction);
httppost.setHeader("Content-Type", "text/xml; charset=utf-8");
String responseString = "Nothingggg";
try {
// the entity holds the request
HttpEntity entity = new StringEntity(envelope);
httppost.setEntity(entity);
// Response handler
ResponseHandler<String> rh = new ResponseHandler<String>() {
// invoked when client receives response
public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
// get response entity
HttpEntity entity = response.getEntity();
// read the response as byte array
StringBuffer out = new StringBuffer();
byte[] b = EntityUtils.toByteArray(entity);
// write the response byte array to a string buffer
out.append(new String(b, 0, b.length));
return out.toString();
}
};
responseString = httpClient.execute(httppost, rh);
} catch (Exception e) {
e.printStackTrace();
Log.d("me","Exc : "+ e.toString());
}
// close the connection
httpClient.getConnectionManager().shutdown();
return responseString;
}
Чтобы удалить атрибуты id e c:root установите для украшений значение false:
envelope.setAddAdornments(false);
чтобы удалить атрибут i: type, для SimpleTypes установите для неявных типов значение true
envelope.implicitTypes = true;
но при работе с ComplexTypes для удаления "i:type" вам понадобится ksoap 3.0.0 RC1 или выше. Сейчас я использую 3.0.0 RC2, но я обновлю стабильную версию 3.0.0, когда она станет доступной.
Этот общий образец является рабочим примером. Веб-запрос мыла отправляет: 90 и возвращает «девяносто».
функциональный интерфейс:
package com.mindef.idttpda.soap;
// function interface for two parameters
@FunctionalInterface
public interface Function2<One, Two> {
public void apply(One one, Two two);
}
класс запроса мыла (с несколькими параметрами :-):
package com.mindef.idttpda.soap;
// dependencies
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import java.util.Map;
/**
* class for executing soap web service call.
*/
public class SoapRequest implements Runnable {
// soap response comes in here
SoapResponse soapResponse;
// webservice variables
String url, namespace, method, action;
// list of parameters for web service method
Map<String, Object> parameters;
/**
* soap call to webservice
* @param parameters - list with parameters for method of web service call.
* @param soapResponse - response of web service call is put in here
*/
public SoapRequest(Map<String, Object> parameters, SoapResponse soapResponse) {
this.parameters = parameters;
this.soapResponse = soapResponse;
}
/**
* set url of web service
* example: https://www.dataaccess.com/webservicesserver/NumberConversion.wso
* @param url - url of web service
* @return this - for method chaining
*/
public SoapRequest url(String url) {
this.url = url;
return this;
}
/**
* set namespace of web service
* example: http://www.dataaccess.com/webservicesserver/
* @param namespace - namespace of webservice
* @return this - for method chaining
*/
public SoapRequest namespace(String namespace){
this.namespace = namespace;
return this;
}
/**
* set method of web service
* example: NumberToWords
* @param method - method to call on web service
* @return this - for method chaining
*/
public SoapRequest method(String method){
this.method = method;
return this;
}
/**
* set soap action of web service call
* example: https://www.dataaccess.com/webservicesserver/NumberConversion.wso/NumberToWords
* @param action - full name of action to call on webservice
* @return this - for method chaining
*/
public SoapRequest action(String action){
this.action = action;
return this;
}
/**
* execute soap web service call
*/
@Override
public void run() {
// soap object.
SoapObject soapObject = new SoapObject(this.namespace, this.method);
// create parameters
for(Map.Entry<String, Object> parameter : parameters.entrySet()) {
PropertyInfo propertyInfo = new PropertyInfo();
propertyInfo.setName(parameter.getKey());
propertyInfo.setValue(parameter.getValue());
propertyInfo.setType(String.class);
soapObject.addProperty(propertyInfo);
}
// make soap envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(soapObject);
// execute web request
HttpTransportSE httpTransportSE = new HttpTransportSE(url);
try {
httpTransportSE.call(action, envelope);
SoapPrimitive soapPrimitive = (SoapPrimitive) envelope.getResponse();
soapResponse.complete(soapPrimitive.toString());
}
// exception handling
catch (Exception e) {
e.printStackTrace();
}
}
/**
* call soap web service
*/
public void call() {
new Thread(this).start();
}
};
ответ мыла:
package com.mindef.idttpda.soap;
// dependencies
import android.view.View;
/**
* class for executing function with response.
*/
public class SoapResponse {
// operation executed when response is received from web service
Function2<View, String> completeFunction;
// view where operation is executed on.
View view;
/**
* soap response from soap web request.
* @param view - view where function is executed on
* @param completeFunction - function to execute when response is received
*/
public SoapResponse(View view, Function2<View, String> completeFunction) {
this.view = view;
this.completeFunction = completeFunction;
}
/**
* execute function with response
* @param response - response from soap web request
*/
public void complete(String response) {
completeFunction.apply(view, response);
}
}
как вызвать метод веб-службы мыла:
/**
* load userlist from database and put in spinner
*/
private void loadWhatever(View loginView) {
// execute soap web request.
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("ubiNum","90");
SoapResponse soapResponse = new SoapResponse(loginView, (view, string) -> this.loginOperation(view, string));
new SoapRequest(parameters, soapResponse)
.url("https://www.dataaccess.com/webservicesserver/NumberConversion.wso")
.namespace("http://www.dataaccess.com/webservicesserver/")
.action("https://www.dataaccess.com/webservicesserver/NumberConversion.wso/NumberToWords")
.method("NumberToWords")
.call();
Замените лямбда-выражение своей собственной функцией. Лямбда-функция существует, поэтому ее можно заменить любой функцией, для которой вы хотите использовать ответ веб-службы мыла. Вы должны сохранить лямбда-подпись.
(view, string) -> this.loginOperation(view, string)