{"id":19696318,"url":"https://github.com/huysentruitw/sapnwrfc","last_synced_at":"2025-05-15T16:02:48.691Z","repository":{"id":40346329,"uuid":"251279723","full_name":"huysentruitw/SapNwRfc","owner":"huysentruitw","description":"SAP NetWeaver RFC library for .NET 5, .NET Core and .NET Framework","archived":false,"fork":false,"pushed_at":"2025-03-13T17:36:56.000Z","size":180,"stargazers_count":159,"open_issues_count":14,"forks_count":46,"subscribers_count":10,"default_branch":"develop","last_synced_at":"2025-05-11T03:58:01.605Z","etag":null,"topics":["bapi","csharp","dotnet","dotnet-core","dotnet5","dotnetcore","netweaver","sap","sap-netweaver","sap-netweaver-sdk","sap-rfc","saprfc"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/huysentruitw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"huysentruitw"}},"created_at":"2020-03-30T11:05:46.000Z","updated_at":"2025-04-29T07:36:20.000Z","dependencies_parsed_at":"2024-06-21T13:04:01.615Z","dependency_job_id":"c8d484a9-10a9-434f-8ea3-9a6e8492572c","html_url":"https://github.com/huysentruitw/SapNwRfc","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huysentruitw%2FSapNwRfc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huysentruitw%2FSapNwRfc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huysentruitw%2FSapNwRfc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huysentruitw%2FSapNwRfc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huysentruitw","download_url":"https://codeload.github.com/huysentruitw/SapNwRfc/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254374398,"owners_count":22060609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bapi","csharp","dotnet","dotnet-core","dotnet5","dotnetcore","netweaver","sap","sap-netweaver","sap-netweaver-sdk","sap-rfc","saprfc"],"created_at":"2024-11-11T19:34:40.924Z","updated_at":"2025-05-15T16:02:48.649Z","avatar_url":"https://github.com/huysentruitw.png","language":"C#","funding_links":["https://github.com/sponsors/huysentruitw"],"categories":[],"sub_categories":[],"readme":"# SAP NetWeaver RFC library\n\n[![Build status](https://github.com/huysentruitw/SapNwRfc/actions/workflows/build-test-publish.yml/badge.svg?branch=master)](https://github.com/huysentruitw/SapNwRfc/actions/workflows/build-test-publish.yml?query=branch%3Amaster)\n\nThis cross-platform library allows you to call SAP NetWeaver RFC functions from .NET 5+, .NET Core and the .NET Framework.\n\nThe library is fully tested and production ready. Supported operating systems are Windows, Linux and macOS.\n\nAlso supports connection pooling for more complex applications, see [below](#connection-pooling).\n\n## Get it on [NuGet](https://www.nuget.org/packages/SapNwRfc/)\n\n    dotnet add package SapNwRfc\n    \nor\n\n    PM\u003e Install-Package SapNwRfc\n\n## Prerequisites\n\nThis 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](https://launchpad.support.sap.com/#/notes/2573790).\n\nYou 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.\n\nOn 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](https://www.microsoft.com/en-us/download/details.aspx?id=40784).\n\n### MacOSX and DYLD_LIBRARY_PATH\n\nWhen 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](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html) Apple has added to OSX.\n\nThe simplest solution to this problem is to make sure the SAP binaries are placed in the working directory of your application.\n\nor to use the [`NativeLibrary.SetDllImportResolver`](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.nativelibrary.setdllimportresolver?view=net-5.0) method in your application.\n\nA more flexible workaround is to set the import resolver for the `SapLibrary` using the [SetDllImportResolver](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.nativelibrary.setdllimportresolver?view=net-5.0)-method like this:\n\n```c#\nNativeLibrary.SetDllImportResolver(\n    assembly: typeof(SapLibrary).Assembly,\n    resolver: (string libraryName, Assembly assembly, DllImportSearchPath? searchPath) =\u003e\n    {\n        if (libraryName == \"sapnwrfc\")\n        {\n            NativeLibrary.TryLoad(\n                libraryPath: Path.Combine(\"\u003cyour_sap_rfc_binaries_path\u003e\", libraryName),\n                handle: out IntPtr handle);\n\n            return handle;\n        }\n\n        return IntPtr.Zero;\n    });\n```\n\n## Usage\n\n### Connect with SAP NetWeaver\n\n```csharp\nstring connectionString = \"AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=8\";\n\nusing var connection = new SapConnection(connectionString);\nconnection.Connect();\n```\n\n### Call function without input or output parameters\n\n```csharp\nusing var someFunction = connection.CreateFunction(\"BAPI_SOME_FUNCTION_NAME\");\nsomeFunction.Invoke();\n```\n\n### Call function with input parameters but no output parameters\n\n```csharp\nclass SomeFunctionParameters\n{\n    [SapName(\"SOME_FIELD\")]\n    public string SomeField { get; set; }\n}\n\nusing var someFunction = connection.CreateFunction(\"BAPI_SOME_FUNCTION_NAME\");\nsomeFunction.Invoke(new SomeFunctionParameters\n{\n    SomeField = \"Some value\",\n});\n```\n\n### Call function with input and output parameters\n\n```csharp\nclass SomeFunctionParameters\n{\n    [SapName(\"SOME_FIELD\")]\n    public string SomeField { get; set; }\n}\n\nclass SomeFunctionResult\n{\n    [SapName(\"RES_ABC\")]\n    public string Abc { get; set; }\n}\n\nusing var someFunction = connection.CreateFunction(\"BAPI_SOME_FUNCTION_NAME\");\nvar result = someFunction.Invoke\u003cSomeFunctionResult\u003e(new SomeFunctionParameters\n{\n    SomeField = \"Some value\",\n});\n\n// Do something with result.Abc\n```\n\n### Call function with dynamic input and output parameters\n\n```csharp\nusing var someFunction = connection.CreateFunction(\"BAPI_SOME_FUNCTION_NAME\");\nvar result = someFunction.Invoke\u003cdynamic\u003e(new\n{\n    SOME_FIELD = \"Some value\",\n});\n\nstring abc = result.RES_ABC;\n```\n\n### Define models with a nested structure\n\n```csharp\nclass SomeFunctionResult\n{\n    [SapName(\"RES_ABC\")]\n    public string Abc { get; set; }\n\n    [SapName(\"RES_ADDR\")]\n    public SomeFunctionResultItem Address { get; set; }\n}\n\nclass SomeFunctionResultAddress\n{\n    [SapName(\"STREET\")]\n    public string Street { get; set; }\n\n    [SapName(\"NR\")]\n    public string Number { get; set; }\n}\n```\n\n### Define models with a nested table\n\n```csharp\nclass SomeFunctionResult\n{\n    [SapName(\"RES_ABC\")]\n    public string Abc { get; set; }\n\n    [SapName(\"RES_ITEMS\")]\n    public SomeFunctionResultItem[] Items { get; set; }\n}\n\nclass SomeFunctionResultItem\n{\n    [SapName(\"ITM_NAME\")]\n    public string Name { get; set; }\n}\n```\n\n### Define models with an IEnumerable\n\n```csharp\nclass SomeFunctionResult\n{\n    [SapName(\"RES_ITEMS\")]\n    public IEnumerable\u003cSomeFunctionResultItem\u003e Items { get; set; }\n}\n\nclass SomeFunctionResultItem\n{\n    [SapName(\"ITM_NAME\")]\n    public string Name { get; set; }\n}\n```\n\n### Exclude properties from mapping\n\n```csharp\nclass SomeFunctionParameters\n{\n    [SapIgnore]\n    public string IgnoredProperty { get; set; }\n\n    [SapName(\"SOME_FIELD\")]\n    public string SomeField { get; set; }\n}\n\nclass SomeFunctionResult\n{\n    [SapIgnore]\n    public string IgnoredProperty { get; set; }\n\n    [SapName(\"SOME_FIELD\")]\n    public string SomeField { get; set; }\n}\n```\n\n### RFC Server Generic Handler\n\n```csharp\nstring connectionString = \"AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=8\";\n\nSapServer.InstallGenericServerFunctionHandler((string functionName, SapAttributes attributes) =\u003e\n{\n    using var connection = new SapConnection(connectionString);\n    connection.Connect();\n    return connection.GetFunctionMetadata(functionName);\n});\n```\n\n### RFC Server\n\n```csharp\nstring connectionString = \"GatewayHost=MY_GW_HOST; GatewayService=MY_GW_SERV; ProgramId=MY_PROGRAM_ID; RegistrationCount=1\";\n\nusing var server = SapServer.Create(connectionString, (ISapServerConnection connection, ISapServerFunction function) =\u003e\n{\n    var attributes = connection.GetAttributes();\n\n    switch (function.GetName())\n    {\n        case \"BAPI_SOME_FUNCTION_NAME\":\n            var parameters = function.GetParameters\u003cSomeFunctionParameters\u003e();\n            function.SetResult(new SomeFunctionResult { Abc = \"Some Value\" });\n        break;\n    }\n});\nserver.Error += (object sender, SapServerErrorEventArgs args) =\u003e Console.WriteLine(args.Error.Message);\nserver.StateChange += (object sender, SapServerStateChangeEventArgs args) =\u003e Console.WriteLine(args.OldState + \" -\u003e \" + args.NewState);\nserver.Launch();\n```\n\n### Type Metadata\n\n```csharp\nvar typeMetadata = connection.GetTypeMetadata(\"MY_STRUCTURE\");\nvar typeName = typeMetadata.GetTypeName();\nvar fieldCount = typeMetadata.Fields.Count;\nforeach (var fieldMetadata in typeMetadata.Fields)\n{\n    var fieldName = fieldMetadata.Name;\n    var fieldType = fieldMetadata.Type;\n}\ntypeMetadata.Fields.TryGetValue(\"FIELD_NAME\", out var fieldNameMetadata);\n```\n\n### Function Metadata\n\n```csharp\nvar functionMetadata = connection.GetFunctionMetadata(\"BAPI_SOME_FUNCTION_NAME\");\nvar functionName = functionMetadata.GetName();\nvar parameterCount = functionMetadata.Parameters.Count;\nforeach (var parameterMetadata in functionMetadata.Parameters)\n{\n    var parameterName = parameterMetadata.Name;\n    var parameterType = parameterMetadata.Type;\n}\nfunctionMetadata.Parameters.TryGetValue(\"PARAMETER_NAME\", out var parameterNameMetadata);\n```\n\n### Ensure the SAP RFC SDK binaries are present\n\n```csharp\nSapLibrary.EnsureLibraryPresent();\n```\n\nThis will throw an [SapLibraryNotFoundException](/src/SapNwRfc/Exceptions/SapLibraryNotFoundException.cs) with a meaningful message in case the SAP RFC SDK binaries were not found.\n\n## Connection String parameters\n\nThe [SapConnection](/src/SapNwRfc/SapConnection.cs) and [SapConnectionPool](/src/SapNwRfc/Pooling/SapConnectionPool.cs) class both take a [SapConnectionParameters](/src/SapNwRfc/SapConnectionParameters.cs) instance or a connection string in the form of:\n\n```csharp\n\"AppServerHost=MY_SERVER_HOST; SystemNumber=00; User=MY_SAP_USER; Password=SECRET; Client=100; Language=EN; PoolSize=5; Trace=3\";\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here to expand the list of supported connection parameters.\u003c/summary\u003e\n\n  | Field                        | SAP Field\n  |:---------------------------- |:---\n  | AppServerHost                | ASHOST\n  | SncLibraryPath               | SNC_LIB\n  | SncQop                       | SNC_QOP\n  | Trace                        | TRACE\n  | SapRouter                    | SAPROUTER\n  | NoCompression                | NO_COMPRESSION\n  | OnCharacterConversionError   | ON_CCE\n  | CharacterFaultIndicatorToken | CFIT\n  | MaxPoolSize                  | MAX_POOL_SIZE\n  | PoolSize                     | POOL_SIZE\n  | SncPartnerNames              | SNC_PARTNER_NAMES\n  | IdleTimeout                  | IDLE_TIMEOUT\n  | MaxPoolWaitTime              | MAX_POOL_WAIT_TIME\n  | RegistrationCount            | REG_COUNT\n  | PasswordChangeEnforced       | PASSWORD_CHANGE_ENFORCED\n  | Name                         | NAME\n  | RepositoryDestination        | REPOSITORY_DESTINATION\n  | RepositoryUser               | REPOSITORY_USER\n  | RepositoryPassword           | REPOSITORY_PASSWD\n  | RepositorySncMyName          | REPOSITORY_SNC_MYNAME\n  | RepositoryX509Certificate    | REPOSITORY_X509CERT\n  | IdleCheckTime                | IDLE_CHECK_TIME\n  | SncMyName                    | SNC_MYNAME\n  | SncPartnerName               | SNC_PARTNERNAME\n  | ProgramId                    | PROGRAM_ID\n  | AppServerService             | ASSERV\n  | MessageServerHost            | MSHOST\n  | MessageServerService         | MSSERV\n  | R3Name                       | R3NAME\n  | LogonGroup                   | GROUP\n  | GatewayHost                  | GWHOST\n  | GatewayService               | GWSERV\n  | SystemNumber                 | SYSNR\n  | User                         | USER\n  | AliasUser                    | ALIAS_USER\n  | SncMode                      | SNC_MODE\n  | Client                       | CLIENT\n  | Password                     | PASSWD\n  | Codepage                     | CODEPAGE\n  | PartnerCharSize              | PCS\n  | SystemId                     | SYSID\n  | SystemIds                    | SYS_IDS\n  | X509Certificate              | X509CERT\n  | SapSso2Ticket                | MYSAPSSO2\n  | UseSapGui                    | USE_SAPGUI\n  | AbapDebug                    | ABAP_DEBUG\n  | LogonCheck                   | LCHECK\n  | Language                     | LANG\n\u003c/details\u003e\n\nAdditional connection parameters can be added by creating a class that inherits from [SapConnectionParameters](/src/SapNwRfc/SapConnectionParameters.cs):\n\n```csharp\npublic class MySapConnectionParameters : SapConnectionParameters\n{\n    [SapName(\"CST_PARAM\")]\n    public string CustomParameter { get; set; }\n}\n```\n\n## Input and output mapping\n\nInput 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.\n\nFor each input and output model type, the library builds and caches a mapping function using expression trees.\n\nSAP RFC parameter types don't have to be specified as they're converted by convention. Here's an overview of supported type mappings:\n\n| C# type           | SAP RFC type                        | Remarks\n|:---------------   |:----------------------------        |:---\n| `int`             | RFCTYPE_INT                         | 4-byte integer\n| `long`            | RFCTYPE_INT8                        | 8-byte integer\n| `double`          | RFCTYPE_FLOAT                       | Floating point, double precision\n| `decimal`         | RFCTYPE_BCD                         |\n| `string`          | RFCTYPE_STRING / RFCTYPE_CHAR / ... | Gets a data field as string \n| `byte[]`          | RFCTYPE_BYTE                        | Raw binary data, fixed length. Has to be used in conjunction with the `[SapBufferLength]`-attribute\n| `char[]`          | RFCTYPE_CHAR                        | Char data, fixed length. Has to be used in conjunction with the `[SapBufferLength]`-attribute\n| `DateTime?`       | RFCTYPE_DATE                        | Only the day, month and year value is used\n| `TimeSpan?`       | RFCTYPE_TIME                        | Only the hour, minute and second value is used\n| `T`               | RFCTYPE_STRUCTURE                   | Structures are constructed from nested objects (T) in the input or output model (see [example](#define-models-with-a-nested-structure))\n| `Array\u003cT\u003e`        | RFCTYPE_TABLE                       | Tables are constructed from arrays of nested objects (T) in the input or output model (see [example](#define-models-with-a-nested-table))\n| `IEnumerable\u003cT\u003e`  | RFCTYPE_TABLE                       | Tables returned as IEnumerable\u003cT\u003e. Yields elements one-by-one for better memory management when handling large datasets\n\n## Connection pooling\n\nThe usage examples above are for simple applications that execute functions one-by-one on a single connection.\n\nFor more complex applications that require concurrency, connection pooling and retry on disconnect, it is advised to use the [`SapPooledConnection`](/src/SapNwRfc/Pooling/SapPooledConnection.cs) and [`SapConnectionPool`](/src/SapNwRfc/Pooling/SapConnectionPool.cs) from the `Pooling` namespace.\n\nSee the [`SapConnectionPool`](/src/SapNwRfc/Pooling/SapConnectionPool.cs) class for configuration options. \n\n### Connection pooling in ASP.NET Core application\n\n#### Register pool and pooled connection\n\nIn the Startup.cs `ConfigureServices` method, add:\n\n```csharp\nservices.AddSingleton\u003cISapConnectionPool\u003e(_ =\u003e new SapConnectionPool(connectionString));\nservices.AddScoped\u003cISapPooledConnection, SapPooledConnection\u003e();\n```\n\n#### Resolve a connection from the pool\n\nIn an `ApiController` or service, do:\n\n```csharp\n[ApiController]\npublic class UserController : ControllerBase\n{\n    public UserController(ISapPooledConnection connection)\n    {\n        _connection = connection;\n    }\n\n    [HttpPost]\n    public IActionResult DoSomething(string action)\n    {\n        _connection.InvokeFunction(\"BAPI_SOME_FUNCTION_NAME\");\n        return Ok();\n    } \n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuysentruitw%2Fsapnwrfc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuysentruitw%2Fsapnwrfc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuysentruitw%2Fsapnwrfc/lists"}