SapNwRfcCore.Hosting 2.0.3

dotnet add package SapNwRfcCore.Hosting --version 2.0.3
                    
NuGet\Install-Package SapNwRfcCore.Hosting -Version 2.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SapNwRfcCore.Hosting" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SapNwRfcCore.Hosting" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="SapNwRfcCore.Hosting" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SapNwRfcCore.Hosting --version 2.0.3
                    
#r "nuget: SapNwRfcCore.Hosting, 2.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SapNwRfcCore.Hosting@2.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SapNwRfcCore.Hosting&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=SapNwRfcCore.Hosting&version=2.0.3
                    
Install as a Cake Tool

SAP NetWeaver RFC library

Build status NuGet License

This cross-platform library allows you to call SAP NetWeaver RFC functions from .NET 5+.

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 SapNwRfcCore

// or when using with Dependency Injection
dotnet add package SapNwRfcCore.Hosting

or

PM> Install-Package SapNwRfcCore

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 (direct)

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();

Or setup via dependency injection

string connectionString = "AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=8";

services.AddSapConnector(connectionString);
// or with custom connection parameters
services.AddSapConnector(options => {
    options.AppServerHost = "MY_SERVER_HOST";
    options.SystemNumber = "00";
    options.User = "MY_SAP_USER";
    options.Password = "SECRET";
    options.Client = "100";
    options.Language = "EN";
    options.PoolSize = 5;
    options.Trace = 8;
});


// Inject the ISapConnectionFactory where you need it and create a connection
ISapConnectionFactory _connectionFactory;

using var connection = _connectionFactory.CreateConnection();
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 | IDLE_CHECK_TIME | SncMyName | SNC_MYNAME | SncPartnerName | SNC_PARTNERNAME | ProgramId | PROGRAM_ID | AppServerService | ASSERV | MessageServerHost | MSHOST | MessageServerService | MSSERV | R3Name | R3NAME | LogonGroup | GROUP | GatewayHost | GWHOST | GatewayService | GWSERV | SystemNumber | SYSNR | User | USER | AliasUser | ALIAS_USER | SncMode | SNC_MODE | Client | CLIENT | Password | PASSWD | Codepage | CODEPAGE | PartnerCharSize | PCS | SystemId | SYSID | SystemIds | SYS_IDS | X509Certificate | X509CERT | SapSso2Ticket | MYSAPSSO2 | UseSapGui | USE_SAPGUI | AbapDebug | ABAP_DEBUG | LogonCheck | LCHECK | Language | LANG </details>

Additional connection parameters can be added by creating a class that inherits from SapConnectionParameters:

public class MySapConnectionParameters : SapConnectionParameters
{
    [SapName("CST_PARAM")]
    public string CustomParameter { get; set; }
}

Input and output mapping

Input and output models used in function calls are mapped to and from SAP RFC parameter types by convention. In case the property name of the model differs from the SAP RFC parameter name, the [SapName]-attribute can be used.

For each input and output model type, the library builds and caches a mapping function using expression trees.

SAP RFC parameter types don't have to be specified as they're converted by convention. Here's an overview of supported type mappings:

C# type SAP RFC type Remarks
int RFCTYPE_INT 4-byte integer
long RFCTYPE_INT8 8-byte integer
double RFCTYPE_FLOAT Floating point, double precision
decimal RFCTYPE_BCD
string RFCTYPE_STRING / RFCTYPE_CHAR / ... Gets a data field as string
byte[] RFCTYPE_BYTE Raw binary data, fixed length. Has to be used in conjunction with the [SapBufferLength]-attribute
char[] RFCTYPE_CHAR Char data, fixed length. Has to be used in conjunction with the [SapBufferLength]-attribute
DateTime? RFCTYPE_DATE Only the day, month and year value is used
TimeSpan? RFCTYPE_TIME Only the hour, minute and second value is used
T RFCTYPE_STRUCTURE Structures are constructed from nested objects (T) in the input or output model (see example)
Array<T> RFCTYPE_TABLE Tables are constructed from arrays of nested objects (T) in the input or output model (see example)
IEnumerable<T> RFCTYPE_TABLE Tables returned as IEnumerable<T>. Yields elements one-by-one for better memory management when handling large datasets

Connection pooling

The usage examples above are for simple applications that execute functions one-by-one on a single connection.

For more complex applications that require concurrency, connection pooling and retry on disconnect, it is advised to use the SapPooledConnection and SapConnectionPool from the Pooling namespace.

See the SapConnectionPool class for configuration options.

Connection pooling in ASP.NET Core application

Register pool and pooled connection

In the Startup.cs ConfigureServices method, add:

services.AddSingleton<ISapConnectionPool>(_ => new SapConnectionPool(connectionString));
services.AddScoped<ISapPooledConnection, SapPooledConnection>();
Resolve a connection from the pool

In an ApiController or service, do:

[ApiController]
public class UserController : ControllerBase
{
    public UserController(ISapPooledConnection connection)
    {
        _connection = connection;
    }

    [HttpPost]
    public IActionResult DoSomething(string action)
    {
        _connection.InvokeFunction("BAPI_SOME_FUNCTION_NAME");
        return Ok();
    } 
}
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.3 79 5/6/2026