SapNwRfc
SAP NetWeaver RFC library for .NET 5, .NET Core and .NET Framework
Install / Use
/learn @huysentruitw/SapNwRfcREADME
SAP NetWeaver RFC library
This cross-platform library allows you to call SAP NetWeaver RFC functions from .NET 5+, .NET Core and the .NET Framework.
The library is fully tested and production ready. Supported operating systems are Windows, Linux and macOS.
Also supports connection pooling for more complex applications, see below.
Get it on NuGet
dotnet add package SapNwRfc
or
PM> Install-Package SapNwRfc
Prerequisites
This library requires the SAP NetWeaver RFC Library 7.50 SDK C++ binaries that should be installed locally. For download and installation instructions see SAP Note 2573790.
You can either place the DLL's in your project output folder or put them in a folder available in the systems PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) environment variable.
On Windows, the 7.50 version of the SAP binaries also require you to install the 64-bit version of the Visual C++ 2013 Redistributable package which can be downloaded and installed from here.
MacOSX and DYLD_LIBRARY_PATH
When your application is started as a child-process (f.e. when running it using Visual Studio for Mac), it is possible that the DYLD_LIBRARY_PATH is not forwarded to the child-process. This is because of this runtime protection Apple has added to OSX.
The simplest solution to this problem is to make sure the SAP binaries are placed in the working directory of your application.
or to use the NativeLibrary.SetDllImportResolver method in your application.
A more flexible workaround is to set the import resolver for the SapLibrary using the SetDllImportResolver-method like this:
NativeLibrary.SetDllImportResolver(
assembly: typeof(SapLibrary).Assembly,
resolver: (string libraryName, Assembly assembly, DllImportSearchPath? searchPath) =>
{
if (libraryName == "sapnwrfc")
{
NativeLibrary.TryLoad(
libraryPath: Path.Combine("<your_sap_rfc_binaries_path>", libraryName),
handle: out IntPtr handle);
return handle;
}
return IntPtr.Zero;
});
Usage
Connect with SAP NetWeaver
string connectionString = "AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=8";
using var connection = new SapConnection(connectionString);
connection.Connect();
Call function without input or output parameters
using var someFunction = connection.CreateFunction("BAPI_SOME_FUNCTION_NAME");
someFunction.Invoke();
Call function with input parameters but no output parameters
class SomeFunctionParameters
{
[SapName("SOME_FIELD")]
public string SomeField { get; set; }
}
using var someFunction = connection.CreateFunction("BAPI_SOME_FUNCTION_NAME");
someFunction.Invoke(new SomeFunctionParameters
{
SomeField = "Some value",
});
Call function with input and output parameters
class SomeFunctionParameters
{
[SapName("SOME_FIELD")]
public string SomeField { get; set; }
}
class SomeFunctionResult
{
[SapName("RES_ABC")]
public string Abc { get; set; }
}
using var someFunction = connection.CreateFunction("BAPI_SOME_FUNCTION_NAME");
var result = someFunction.Invoke<SomeFunctionResult>(new SomeFunctionParameters
{
SomeField = "Some value",
});
// Do something with result.Abc
Call function with dynamic input and output parameters
using var someFunction = connection.CreateFunction("BAPI_SOME_FUNCTION_NAME");
var result = someFunction.Invoke<dynamic>(new
{
SOME_FIELD = "Some value",
});
string abc = result.RES_ABC;
Define models with a nested structure
class SomeFunctionResult
{
[SapName("RES_ABC")]
public string Abc { get; set; }
[SapName("RES_ADDR")]
public SomeFunctionResultItem Address { get; set; }
}
class SomeFunctionResultAddress
{
[SapName("STREET")]
public string Street { get; set; }
[SapName("NR")]
public string Number { get; set; }
}
Define models with a nested table
class SomeFunctionResult
{
[SapName("RES_ABC")]
public string Abc { get; set; }
[SapName("RES_ITEMS")]
public SomeFunctionResultItem[] Items { get; set; }
}
class SomeFunctionResultItem
{
[SapName("ITM_NAME")]
public string Name { get; set; }
}
Define models with an IEnumerable
class SomeFunctionResult
{
[SapName("RES_ITEMS")]
public IEnumerable<SomeFunctionResultItem> Items { get; set; }
}
class SomeFunctionResultItem
{
[SapName("ITM_NAME")]
public string Name { get; set; }
}
Exclude properties from mapping
class SomeFunctionParameters
{
[SapIgnore]
public string IgnoredProperty { get; set; }
[SapName("SOME_FIELD")]
public string SomeField { get; set; }
}
class SomeFunctionResult
{
[SapIgnore]
public string IgnoredProperty { get; set; }
[SapName("SOME_FIELD")]
public string SomeField { get; set; }
}
RFC Server Generic Handler
string connectionString = "AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=8";
SapServer.InstallGenericServerFunctionHandler((string functionName, SapAttributes attributes) =>
{
using var connection = new SapConnection(connectionString);
connection.Connect();
return connection.GetFunctionMetadata(functionName);
});
RFC Server
string connectionString = "GatewayHost=MY_GW_HOST; GatewayService=MY_GW_SERV; ProgramId=MY_PROGRAM_ID; RegistrationCount=1";
using var server = SapServer.Create(connectionString, (ISapServerConnection connection, ISapServerFunction function) =>
{
var attributes = connection.GetAttributes();
switch (function.GetName())
{
case "BAPI_SOME_FUNCTION_NAME":
var parameters = function.GetParameters<SomeFunctionParameters>();
function.SetResult(new SomeFunctionResult { Abc = "Some Value" });
break;
}
});
server.Error += (object sender, SapServerErrorEventArgs args) => Console.WriteLine(args.Error.Message);
server.StateChange += (object sender, SapServerStateChangeEventArgs args) => Console.WriteLine(args.OldState + " -> " + args.NewState);
server.Launch();
Type Metadata
var typeMetadata = connection.GetTypeMetadata("MY_STRUCTURE");
var typeName = typeMetadata.GetTypeName();
var fieldCount = typeMetadata.Fields.Count;
foreach (var fieldMetadata in typeMetadata.Fields)
{
var fieldName = fieldMetadata.Name;
var fieldType = fieldMetadata.Type;
}
typeMetadata.Fields.TryGetValue("FIELD_NAME", out var fieldNameMetadata);
Function Metadata
var functionMetadata = connection.GetFunctionMetadata("BAPI_SOME_FUNCTION_NAME");
var functionName = functionMetadata.GetName();
var parameterCount = functionMetadata.Parameters.Count;
foreach (var parameterMetadata in functionMetadata.Parameters)
{
var parameterName = parameterMetadata.Name;
var parameterType = parameterMetadata.Type;
}
functionMetadata.Parameters.TryGetValue("PARAMETER_NAME", out var parameterNameMetadata);
Ensure the SAP RFC SDK binaries are present
SapLibrary.EnsureLibraryPresent();
This will throw an SapLibraryNotFoundException with a meaningful message in case the SAP RFC SDK binaries were not found.
Connection String parameters
The SapConnection and SapConnectionPool class both take a SapConnectionParameters instance or a connection string in the form of:
"AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=3";
<details>
<summary>Click here to expand the list of supported connection parameters.</summary>
| Field | SAP Field |:---------------------------- |:--- | AppServerHost | ASHOST | SncLibraryPath | SNC_LIB | SncQop | SNC_QOP | Trace | TRACE | SapRouter | SAPROUTER | NoCompression | NO_COMPRESSION | OnCharacterConversionError | ON_CCE | CharacterFaultIndicatorToken | CFIT | MaxPoolSize | MAX_POOL_SIZE | PoolSize | POOL_SIZE | SncPartnerNames | SNC_PARTNER_NAMES | IdleTimeout | IDLE_TIMEOUT | MaxPoolWaitTime | MAX_POOL_WAIT_TIME | RegistrationCount | REG_COUNT | PasswordChangeEnforced | PASSWORD_CHANGE_ENFORCED | Name | NAME | RepositoryDestination | REPOSITORY_DESTINATION | RepositoryUser | REPOSITORY_USER | RepositoryPassword | REPOSITORY_PASSWD | RepositorySncMyName | REPOSITORY_SNC_MYNAME | RepositoryX509Certificate | REPOSITORY_X509CERT | IdleCheckTime
Related Skills
node-connect
340.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
340.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.2kCommit, push, and open a PR
