Web Services: SAP Web Service Clients


Alpha Anywhere has been used by some customers to connect to SAP web services. This article summarizes experience gained in working with those customers.

The following discussion assumes you have previous experience with SOAP Web Services and Alpha Anywhere. If you have not read the help topic SOAP Services you may want to start there.

Connecting to SAP Web Services

The appropriate binding and credential settings for SAP services appear to be the following:

DIM binding as System::ServiceModel::BasicHttpBinding
binding.Security.Mode = System::ServiceModel::BasicHttpSecurityMode::TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = System::ServiceModel::HttpClientCredentialType::Basic

DIM endpoint as System::ServiceModel::EndpointAddress = new System::ServiceModel::EndPointAddress(ServiceURL)

DIM Client as MyNamespace::GetList_OutClient = new MyNamespace::GetList_OutClient(Binding, EndPoint)
Client.ClientCredentials.HttpDigest.AllowedImpersonationLevel.value__ =  3 ' Impersonation
Client.ClientCredentials.HttpDigest.ClientCredential.UserName = UserName
Client.ClientCredentials.HttpDigest.ClientCredential.Password = Password
Client.ClientCredentials.UserName.UserName = UserName
Client.ClientCredentials.UserName.Password = Password
ServiceURL, UserName and Password are assumed to be variables in the script that have been populated with the respective values.

SAP Uses a Very Long URL

Most web services use a URL that ends with the name of the service. SAP Web Services pass a lot of information as query parameters. Be sure those query parameters are preserved in the endpoint/Address used for your service call.

For example:


SAP Generates a Separate Service For Each Function

Each function that is generated into a web service becomes a separate web service.

As a result, you will need to treat each function as a completely separate service with its own assembly and client initialization code.

Watch for Timeouts

In some environments, we have noticed issues with timeouts.

You can increase the default timeouts as shown below:

DIM binding as System::ServiceModel::BasicHttpBinding

binding.OpenTimeout    = new System::TimeSpan(0,0,10)    ' Connect
binding.ReceiveTimeout = new System::TimeSpan(0,0,20)    ' Inactivity
binding.SendTimeout    = new System::TimeSpan(0,1,0)     ' Write Operation
binding.CloseTimeout   = new System::TimeSpan(0,0,15)    ' Close Operation

SAP Request and Response Objects Tend to Nest

In the typical request and response pattern discussed in the help topic SOAP Services, there is a class for the request and a class for the response. The call takes the form Response = Client.Method(Request).

SAP web services tend to nest down an additional level, defining a property prefixed with "MT" as shown below. The data type of the the property value tends to have DT as a prefix.

' Create the request, response and client
DIM Request as ::MyService::GetList_OutRequest
DIM Response as ::MyService::GetList_OutResponse
Request.MT_GetList_Request = new ::MyService::DT_GetList_Request()
Request.MT_GetList_Request.RequestId = "1"

' Call the service
Response = Client.GetList_Out(Request)

' Check the call status
DIM ListResponse as ::MyService::DT_GetList_Response = Response.MT_GetList_Response

' If values returned are in an array, you can walk through the array as follows:
for i = 1 to ListResponse.Get.Count
    Items = Plants + ListResponse.Get.GetValue(1).Item + crlf()

Working with Date Fields

An error can occur when passing datetime fields to an SAP service that defines an element as type xsd:datetime. The SOAP UI format of the date (2017-01-25T13:21:32.8908456-06:00) is slightly different than the one generating the error (2018-02-02T18:25:23.793 - note that in this case it has seven digits of fractional time whereas the reported SOAP error only has three).

Passing DateTime values to SAP from WCF clients is a known issue. Here are a couple of links to related posts.

The most effective workaround to this issue so far requires making a change to the WSDL file and regenerating the client.

  1. Download and save the WSDL file by referencing the URL for the WSDL in a browser and saving the contents to a text file.

  2. Edit the WSDL file, changing the field type of the offending element (Order_Date in this example) from "xsd:datetime" to "xsd:string".

    <xsd:element name="Order_Date" type="xsd:string" >
            <xsd:appinfo source="http://sap.com/xi/TextID">d8d78f827aae11e28b885c260a3a7662</xsd:appinfo>
  3. Rebuild the WCF client from the new WSDL file using Dotnet::Services::GenerateWCFServiceFromWSDL().

  4. In Xbasic code that assigns the field, replace the assignment of the current date as follows:

    objHeader.Order_Date = now()


    objHeader.Order_Date = System::String::Format("{0:yyyy-MM-ddTHH:mm:ss.fffffffZ}", now())
    In this example, we use "now()". The source may also be a datetime variable or datetime literal.