试图建立一个正确的SOAP请求建立一个、正确、SOAP

2023-09-13 00:40:58 作者:三重门。

我一直在挣扎了几个小时试图建立使用kso​​ap2为Android,没有运气正确的SOAP请求。理想的要求是这样的:

I have been struggling for hours trying to build the correct SOAP request using ksoap2 for Android with no luck. The ideal request looks like this:

<?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:Header>
    <AuthorizationToken xmlns="http://www.avectra.com/2005/">
      <Token>string</Token>
    </AuthorizationToken>
  </soap:Header>
  <soap:Body>
    <ExecuteMethod xmlns="http://www.avectra.com/2005/">
      <serviceName>string</serviceName>
      <methodName>string</methodName>
      <parameters>
        <Parameter>
          <Name>string</Name>
          <Value>string</Value>
        </Parameter>
      </parameters>
    </ExecuteMethod>
  </soap:Body>
</soap:Envelope>

我使用下面的code生成我的要求:

I am using the following code to generate my request:

    SoapObject request = new SoapObject(NAMESPACE, METHOD);
    request.addProperty("serviceName", SERVICENAME);
    request.addProperty("methodName", METHODNAME);

    SoapObject nestedParameters = new SoapObject(NAMESPACE, "parameters");
    SoapObject param = new SoapObject(NAMESPACE, "Parameter");
    param.addProperty("Name", name);
    param.addProperty("Value", value);
    nestedParameters.addSoapObject(param);
    request.addSoapObject(nestedParameters);

    SoapSerializationEnvelope envelope = 
            new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.setOutputSoapObject(request);
    envelope.dotNet = true;
    envelope.implicitTypes = true;

    envelope.headerOut = new Element[1];
    Element header = new Element().createElement(NAMESPACE, "AuthorizationToken");
    Element token = new Element().createElement(NAMESPACE, "Token");
    token.addChild(Node.TEXT, this.AUTH_TOKEN);
    header.addChild(Node.ELEMENT, token);
    envelope.headerOut[0] = header;

什么ksoap2正在建设的是:

What ksoap2 is building is:

<v:Envelope xmlns:i="http://www.w3.org/1999/XMLSchema-instance" xmlns:d="http://www.w3.org/1999/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
  <v:Header>
    <n0:AuthorizationToken xmlns:n0="http://www.avectra.com/2005/">
      <n0:Token>string</n0:Token>
    </n0:AuthorizationToken>
  </v:Header>
  <v:Body>
    <ExecuteMethod xmlns="http://www.avectra.com/2005/" id="o0" c:root="1">   
      <serviceName>AHAWebServices</serviceName>
      <methodName>MemberDirectory</methodName>
      <parameters i:type="n1:parameters" xmlns:n1="http://www.avectra.com/2005/">
        <Parameter i:type="n1:Parameter">
          <Name>string</Name>
          <Value>string</Value>
        </Parameter>
      </parameters>
    </ExecuteMethod>
  </v:Body>
</v:Envelope>

我有一种感觉,这个问题是与N0 prefixes头,但我不知道如何摆脱他们。我删除它们从身体通过设置implicitTypes为真,但我找不到头类似的设置。我是新来的SOAP所以任何其他的建议是极大的AP preciated。任何人都不会有的,我怎么能解决这个问题的想法?

I have a feeling that the problem is in the header with the n0 prefixes but I have no clue how to get rid of them. I removed them from from the body by setting implicitTypes to true but I cannot find a similar setting for the header. I am new to SOAP so any other advice is greatly appreciated. Does anyone have an idea of how I could fix this?

推荐答案

当使用KSOAP这为我工作

SoapObject request = new SoapObject(WEBSERVICE_NAMESPACE, methodName);
    if(null != parameterMap && !parameterMap.isEmpty()){
        for(Entry<String, String> entry: parameterMap.entrySet()){
            request.addProperty(entry.getKey(), entry.getValue());
        }
    }
    // Declare the version of the SOAP request

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.implicitTypes = true;
    envelope.dotNet = true;
    envelope.setOutputSoapObject(request);


    HttpTransportSE androidHttpTransport = new HttpTransportSE(ApplicationConstants.WEBSERVICE_WSDL_URL);

    // this is the actual part that will call the webservice
    try {

        androidHttpTransport.debug = true;
        androidHttpTransport.call(soapActionUrl, envelope);
        String ss = androidHttpTransport.responseDump;

        // Get the SoapResult from the envelope body.

        Log.d(TAG, "request: " + androidHttpTransport.requestDump);
        Log.d(TAG, "response: "+    androidHttpTransport.responseDump);


        SoapObject result = (SoapObject) envelope.getResponse();

        Log.d("soap response", "" + result);            
    } catch (IOException e) {
        Log.e(TAG, "IOException", e);
    } 

请注意:

androidHttpTransport.debug = true;

在我的情况下解决了问题。拍着我的头,但不能讲理,为什么设置调试真正帮助解决问题。

resolved the issue in my case. Banged my head but could not reason with why setting debug true helped resolve the issue.

为什么需要使用KSOAP? 只要有一个字符串的SOAP请求的静态方,追加值的静态部分,你终于可以有完整的SOAP请求。最后,使用HTTP方法来发送你的post请求。

Why do you need to use ksoap? Simply have the static party of your SOAP request as a String, append the values to the static part and you can finally have the complete SOAP request. Finally use HTTP methods to send your post request.

没有额外的JAR

此外KSOAP有一个像OOM对于大响应等问题

Also ksoap has issues like OOM for large responses, etc.

KSOAP OOM问题

您可以使用下面的code

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.util.Log;

public final class SOAPRequest{

private static final String TAG = "SOAPRequest";
private static final String TAG_SOAP_HEADER_START = "<?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:Header>";
private static final String TAG_AUTHORIZATION_START = "<AuthorizationToken xmlns=\"http://www.avectra.com/2005/\">";
private static final String TAG_TOKEN_START = "<TOKEN>";
private static final String TAG_TOKEN_END = "</TOKEN>";
private static final String TAG_AUTORIZATION_END = "</AuthorizationToken>";
private static final String TAG_SOAPHEADER_END = "</soap:Header>"; 
private static final String TAG_SOAP_BODY_START = "<soap:Body>";
private static final String TAG_PARAM_NAME_START = "<Name>";
private static final String TAG_PARAM_NAME_END = "</Name>";
private static final String TAG_PARAM_VALUE_START = "<Value>";
private static final String TAG_PARAM_VALUE_END = "</Value>";
private static final String TAG_METHOD_START = "<methodName>";
private static final String TAG_METHOD_END = "</methodName>";
private static final String TAG_SERVICE_START = "<serviceName>";
private static final String TAG_SERVICE_END = "</serviceName>";
private static final String TAG_PARAMS_START = "<parameters><Parameter>";
private static final String TAG_EXE_METHOD_START = "<ExecuteMethod xmlns=\"http://www.avectra.com/2005/\">";
private static final String TAG_SOAP_REQ_END = "</Parameter></parameters></ExecuteMethod></soap:Body></soap:Envelope>";

/**
 * Constructor intentionally made private 
 */
private SOAPRequest() {

}
/**
 * Builds a SOAP request with the specified value
 * @param token Value of token
 * @param serviceName Value of servicename
 * @param methodName Value of methodName
 * @param paramsMap Collection of parameters as set of name value pair which needs to be sent
 * @return the complete soap request
 */
public static String buildRequest(String token, String serviceName, String methodName, HashMap<String, String> paramsMap){
    StringBuilder requestBuilder = new StringBuilder(TAG_SOAP_HEADER_START);
    requestBuilder.append(TAG_AUTHORIZATION_START);
    requestBuilder.append(TAG_TOKEN_START);
    requestBuilder.append(token);
    requestBuilder.append(TAG_TOKEN_END);
    requestBuilder.append(TAG_AUTORIZATION_END);
    requestBuilder.append(TAG_SOAPHEADER_END);
    requestBuilder.append(TAG_SOAP_BODY_START);
    requestBuilder.append(TAG_EXE_METHOD_START);
    requestBuilder.append(TAG_SERVICE_START);
    requestBuilder.append(serviceName);
    requestBuilder.append(TAG_SERVICE_END);
    requestBuilder.append(TAG_METHOD_START);
    requestBuilder.append(methodName);
    requestBuilder.append(TAG_METHOD_END);
    requestBuilder.append(TAG_PARAMS_START);
    for(Entry<String, String> param :paramsMap.entrySet()){
        requestBuilder.append(TAG_PARAM_NAME_START);
        requestBuilder.append(param.getKey());
        requestBuilder.append(TAG_PARAM_NAME_END);
        requestBuilder.append(TAG_PARAM_VALUE_START);
        requestBuilder.append(param.getValue());
        requestBuilder.append(TAG_PARAM_VALUE_END);
    }
    requestBuilder.append(TAG_SOAP_REQ_END);
    return requestBuilder.toString();
}

/**
 * Connection timeout set for the HttpClient
 */
private static final int CONNECTION_TIMEOUT= 6000;
/**
 * Socket timeout set for the HttpClient
 */
private static final int SOCKET_TIMEOUT = 10000; 

/**
 * @return httpClient An instance of {@link DefaultHttpClient}
 */
private static DefaultHttpClient getHttpClient() {
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used.
    HttpConnectionParams.setConnectionTimeout(httpParameters,CONNECTION_TIMEOUT);
    // Set the default socket timeout (SO_TIMEOUT)
    // in milliseconds which is the timeout for waiting for data.
    HttpConnectionParams.setSoTimeout(httpParameters, SOCKET_TIMEOUT);

    return new DefaultHttpClient(httpParameters);
}

/**
 * Sends a SOAP request to the specified service endpoint. 
 * 
 * @param serviceEndpoint The service endpoint which will be hit
 * @param soapRequest The SOAP request
 * @return The string representing the response for the specified SOAP request. 
 */
public static String send(String serviceEndpoint, String soapRequest){
    HttpPost httppost = new HttpPost(serviceEndpoint);          
    StringEntity se = null;
    try {
        se = new StringEntity(soapRequest,HTTP.UTF_8);
    } catch (UnsupportedEncodingException e) {
        Log.e(TAG,"send", e);
        return null;
    }

    se.setContentType("text/xml");  
    httppost.setHeader("Content-Type","application/soap+xml;charset=UTF-8");
    httppost.setEntity(se);  
    String result = null;
    HttpClient httpclient = getHttpClient();
    try {
        HttpResponse httpResponse = httpclient.execute(httppost);
        HttpEntity responseEntity = httpResponse.getEntity();
        if(null!= responseEntity){
            //if you have a huge chunk of data read it using a buffer
            result =EntityUtils.toString(responseEntity);
        }
    } catch (ClientProtocolException e) {
        Log.e(TAG,"send", e);
    } catch (IOException e) {
        Log.e(TAG,"send", e);
    } catch (Exception e){
        Log.e(TAG,"send", e);
    }

    return result;
}

}