Web Services: SAP Web Service Clients
Overview
Alpha Anywhere has been used by some customers to connect to SAP web services. This article summarizes experience gained in working with those customers.
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
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:
http://server.domain.com:51000/XISOAPAdapter/MessageServlet?senderParty=&senderService=BS_XXXX_Q&receiverParty=&receiverService=&interface=GetList_Out&interfaceNamespace=http://XXXX.com//XXXX/GetList/DR6001
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() next
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.
Download and save the WSDL file by referencing the URL for the WSDL in a browser and saving the contents to a text file.
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:annotation> <xsd:appinfo source="http://sap.com/xi/TextID">d8d78f827aae11e28b885c260a3a7662</xsd:appinfo> </xsd:annotation> </xsd:element>
Rebuild the WCF client from the new WSDL file using Dotnet::Services::GenerateWCFServiceFromWSDL().
In Xbasic code that assigns the field, replace the assignment of the current date as follows:
objHeader.Order_Date = now()
becomesobjHeader.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.