Recently we’ve been asked to migrate a few data flows running on proprietary software to Azure. The flows were not complicated; the only specialty was that we had to call some SAP RFC functions. As we have already implemented several Logic App workflows using SAP connectors capable of doing such calls we haven’t seen a problem. However, when we tried to connect to the target SAP, we received the following error message: “Required parameters ‘[rfcGroupFilter]’ not set or invalid.” We’ve double-checked the connection parameters, then the error logs on the on-premise data gateway but we haven’t found anything strange. But when we compared side by side the Logic App that is working correctly with the one giving us the error we realized that in case of the error, we are targeting a different (older) version of SAP and there might be a compatibility problem.
As we’ve been unable to find out how to do it in Logic App, we’ve started to take a look for another solution. Wouldn’t be possible to do it with Azure Function? Let’s quickly summarize what we know and need for that:
Let’s start with the provisioning of the Azure resources. Firstly, I’ve provisioned Azure Function App running on App Service Plan and I’ve created the hybrid connection to SAP. The default SAP port is 3300 but it could vary depending on set-up. In case you need help in creating the hybrid connection you might find some information in one article I’ve written a while ago (https://www.middleway.eu/using-azure-hybrid-connections/).
Right now we can create and deploy our function. In my case, I’ve created the function with Visual Studio using the template for Azure Functions choosing Function worker: “.NET Framework Isolated v4”.
Once the function project is created we need to add the NCo references as mentioned before. You can either install the latest official version of the NCo 3.0 connector from the SAP website (you’ll need the SAP client account to download it) or install it as a NuGet package. For example, the package sapnco_x64 does the job:
This NuGet package does not contain the latest version of the NCo but it’s not a big deal. We have everything to start implementing our Azure Function that can do some SAP calls.
The implementation of the Azure Function to call the SAP RFC function doesn’t differ much from the implementation of other types of .NET applications. The functional code is just placed in the function trigger. In our demo I’ll create an HTTP trigger function where I’m :
And here we are:
[Function("SapRfcCallDemo")] public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req) { // Reading input JSON with parameters dynamic inputParameters = await req.ReadFromJsonAsync<dynamic>(); HttpResponseData response = req.CreateResponse(); response.Headers.Add("Content-Type", "text/plain; charset=utf-8"); try { // Setting up the connection parameters RfcConfigParameters rfcPar = new RfcConfigParameters(); rfcPar.Add(RfcConfigParameters.Name, "ApplicationServer"); rfcPar.Add(RfcConfigParameters.Client, "100"); rfcPar.Add(RfcConfigParameters.User, "sap_user_name"); rfcPar.Add(RfcConfigParameters.Password, "sap_user_password"); // The server host is the same as the one in hybrid connection rfcPar.Add(RfcConfigParameters.AppServerHost, "demosap.domain.com"); rfcPar.Add(RfcConfigParameters.AppServerService, "sapservice"); rfcPar.Add(RfcConfigParameters.SystemNumber, "00"); rfcPar.Add(RfcConfigParameters.Language, "en"); rfcPar.Add(RfcConfigParameters.SncQOP, "Authentication"); // Create the destination RfcDestination dest = RfcDestinationManager.GetDestination(rfcPar); RfcRepository rfcRepository = dest.Repository; IRfcFunction sapFunction = rfcRepository.CreateFunction("MY_RFC_FUNCTION"); sapFunction.SetValue("I_PARAM1", inputParameters.param1); sapFunction.SetValue("I_PARAM2", inputParameters.param2); sapFunction.SetValue("I_PARAM3", inputParameters.param3); // Calling the RFC function sapFunction.Invoke(dest); // Obtaining the result var result = sapFunction.GetTable("MY_RESULT_TABLE"); response.StatusCode = HttpStatusCode.OK; if (result != null) { response.WriteString(result.ToString()); } } catch (Exception ex) { response.StatusCode = HttpStatusCode.InternalServerError; response.WriteString(ex.Message.ToString()); _logger.LogError($"Error occured: {ex.Message}"); } return response; }
Of course, passing the input parameters and configuration has to be adapted to your need. Same for the extracting of results. Note that the value of the AppServerHost parameter should be the same which was specified in the hybrid connection.
What is important to mention is that the function has to be compiled to a specific target platform so the NCo connector works properly. In my case, I’m targeting the build to the “x64” platform. The code built for “Any CPU” won’t work.
Calling SAP RFC functions by using Azure Function is a bit more laborious compared to Logic App connector. However, our solution with Azure Function helped us to overcome the compatibility issues we had. We could as well benefit from Azure Function running in an isolated process. It decouples .NET functions from the Azure Functions host so it was possible for us to use .NET Framework 4.x and NCo while being able to use the latest Azure Function trigger interface and deploy it to the latest Azure Function v4.