RfcClient 0.1.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package RfcClient --version 0.1.1
                    
NuGet\Install-Package RfcClient -Version 0.1.1
                    
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="RfcClient" Version="0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RfcClient" Version="0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="RfcClient" />
                    
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 RfcClient --version 0.1.1
                    
#r "nuget: RfcClient, 0.1.1"
                    
#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 RfcClient@0.1.1
                    
#: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=RfcClient&version=0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=RfcClient&version=0.1.1
                    
Install as a Cake Tool

RfcClient

RfcClient is a DI-friendly SAP RFC client wrapper for SAP .NET Connector.

It targets .NET 10.0. The library supports multiple SAP RFC connection configs, request-scoped ConfigId switching, typed request/response mapping, and connection/invocation monitoring hooks.

Additional documentation:

Features

  • Multiple SAP RFC connection configs by ConfigId
  • Default config selection through IsDefault
  • ASP.NET Core / generic host dependency injection support
  • Request-scoped RFC session switching through IRfcClient.ConfigId
  • Typed RFC input/output mapping with [Table] and [Column]
  • Connection and invocation monitoring extension points
  • SAP NCo runtime files included from project libs

Installation

Install the NuGet package:

dotnet add package RfcClient

The package targets net10.0.

Configuration

Add RFC connection configs to appsettings.json:

{
  "RfcConnectionConfigs": [
    {
      "ConfigId": "Sap",
      "IsDefault": true,
      "ConnectionString": "ApplicationServer=192.168.1.65;SystemNumber=00;SystemId=DEV;Client=800;UserName=DEVUSER;Password=******;Language=ZH;PoolSize=5;MaxPoolSize=10;ConnectionTimeout=30;CommunicationTimeout=60;"
    },
    {
      "ConfigId": "Sap.JSY",
      "IsDefault": false,
      "ConnectionString": "MessageServerHost=192.168.1.65;MessageServerService=3600;SystemId=DEV;Client=800;UserName=DEVUSER;Password=******;Language=ZH;PoolSize=5;MaxPoolSize=10;"
    }
  ]
}

Supported ConnectionString parameters map to RfcConfigParameter:

ApplicationServer
Server
SystemNumber
SystemId
Client
UserName
User ID
UserId
Password
Language
PoolSize
MaxPoolSize
Max Pool Size
ConnectionTimeout
CommunicationTimeout
MessageServerHost
MessageServerService
MessageServerPort

ApplicationServer / Server is used for direct application server connections. MessageServerHost is used for message server connections.

Register Services

Register the client with IServiceCollection. Pass the configuration explicitly, or let it auto-resolve IConfiguration from the DI container:

using RfcClient;

// Option 1: pass configuration explicitly
builder.Services.AddRfcClient(builder.Configuration);

// Option 2: auto-resolve IConfiguration from the DI container
builder.Services.AddRfcClient();

If your SAP RFC settings live under a section:

builder.Services.AddRfcClient(
    builder.Configuration.GetSection("Rfc"));

Programmatic registration is also supported:

using RfcClient;

builder.Services.AddRfcClient(options =>
{
    options.RfcConnectionConfigs.Add(new RfcConnectionConfig
    {
        ConfigId = "Sap",
        IsDefault = true,
        ConnectionString = "ApplicationServer=192.168.1.65;SystemNumber=00;Client=800;UserName=DEVUSER;Password=******;"
    });
});

Define RFC Models

Use [Table] on the request type to declare the RFC function name. Use [Column] on properties to map SAP RFC parameter names.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Table("ZFM_MM039")]
public class SupplyDemandRequest
{
    [Required]
    [Column("IV_MATNR")]
    public string MaterialCode { get; set; } = string.Empty;

    [Required]
    [Column("IV_BUKRS")]
    public string CompanyCode { get; set; } = string.Empty;

    [Column("IV_WERKS")]
    public string PlantCode { get; set; } = string.Empty;

    [Required]
    [Column("IV_SYSTEM")]
    public string Source { get; set; } = string.Empty;
}
using System.ComponentModel.DataAnnotations.Schema;

public class SupplyDemandResponse
{
    [Column("EV_STATUS")]
    public string Status { get; set; } = string.Empty;

    [Column("EV_MESSAGE")]
    public string Message { get; set; } = string.Empty;

    [Column("ET_DATA")]
    public SupplyDemandRow[] Rows { get; set; } = Array.Empty<SupplyDemandRow>();
}

public class SupplyDemandRow
{
    [Column("MATNR")]
    public string MaterialCode { get; set; } = string.Empty;

    [Column("WERKS")]
    public string PlantCode { get; set; } = string.Empty;

    [Column("BDMNG")]
    public decimal Quantity { get; set; }
}

Basic Call

Inject IRfcClient and invoke the RFC with typed request/response models:

using RfcClient.Abstractions;

public class SupplyDemandService
{
    private readonly IRfcClient _rfcClient;

    public SupplyDemandService(IRfcClient rfcClient)
    {
        _rfcClient = rfcClient;
    }

    public SupplyDemandResponse Query()
    {
        var request = new SupplyDemandRequest
        {
            MaterialCode = "B0505XT-1WR3",
            CompanyCode = "1100",
            PlantCode = "",
            Source = "C"
        };

        return _rfcClient.Invoke<SupplyDemandRequest, SupplyDemandResponse>(request);
    }
}

IRfcClient exposes a scoped ConfigId property. If ConfigId is empty, the client uses the config marked with IsDefault=true. If no config is marked as default, it uses the first item in RfcConnectionConfigs.

Switch ConfigId Per Request

Set IRfcClient.ConfigId inside the current request scope. After that, all IRfcClient calls in the same scope use that config automatically.

Example middleware:

using RfcClient.Abstractions;

app.Use(async (context, next) =>
{
    var rfcClient = context.RequestServices.GetRequiredService<IRfcClient>();
    var configId = context.Request.Headers["X-Sap-Rfc-ConfigId"].FirstOrDefault();

    if (!string.IsNullOrWhiteSpace(configId))
    {
        rfcClient.ConfigId = configId;
    }

    await next();
});

Example controller:

using Microsoft.AspNetCore.Mvc;
using RfcClient.Abstractions;

[ApiController]
[Route("api/supply-demand")]
public class SupplyDemandController : ControllerBase
{
    private readonly IRfcClient _rfcClient;

    public SupplyDemandController(IRfcClient rfcClient)
    {
        _rfcClient = rfcClient;
    }

    [HttpPost]
    public ActionResult<SupplyDemandResponse> Query(SupplyDemandRequest request)
    {
        var response = _rfcClient.Invoke<SupplyDemandRequest, SupplyDemandResponse>(request);
        return Ok(response);
    }
}

Calling the API with a header switches the SAP RFC config for that request:

X-Sap-Rfc-ConfigId: Sap.JSY

Call With Explicit ConfigId

Set IRfcClient.ConfigId before invoking when you need explicit control over the RFC config:

using RfcClient.Abstractions;

public class ManualRfcService
{
    private readonly IRfcClient _rfcClient;

    public ManualRfcService(IRfcClient rfcClient)
    {
        _rfcClient = rfcClient;
    }

    public SupplyDemandResponse QueryWithJsy(SupplyDemandRequest request)
    {
        _rfcClient.ConfigId = "Sap.JSY";
        return _rfcClient.Invoke<SupplyDemandRequest, SupplyDemandResponse>(request);
    }
}

Set ConfigId back to an empty string to return to the default configured SAP RFC connection in the same scope.

Monitor Connections And Calls

Implement IRfcConnectionMonitor to observe resolved destinations and RFC invocations:

using Microsoft.Extensions.Logging;
using RfcClient;
using RfcClient.Abstractions;

public class LoggingRfcConnectionMonitor : IRfcConnectionMonitor
{
    private readonly ILogger<LoggingRfcConnectionMonitor> _logger;

    public LoggingRfcConnectionMonitor(ILogger<LoggingRfcConnectionMonitor> logger)
    {
        _logger = logger;
    }

    public void DestinationResolved(RfcDestinationResolvedContext context)
    {
        _logger.LogInformation(
            "SAP RFC destination resolved. ConfigId={ConfigId}, ForceNew={ForceNew}, PoolSize={PoolSize}, MaxPoolSize={MaxPoolSize}",
            context.ConfigId,
            context.ForceNew,
            context.ConfigParameter.PoolSize,
            context.ConfigParameter.MaxPoolSize);
    }

    public void InvocationStarted(RfcInvocationContext context)
    {
        _logger.LogInformation(
            "SAP RFC invocation started. ConfigId={ConfigId}, Function={Function}",
            context.ConfigId,
            context.FunctionName);
    }

    public void InvocationSucceeded(RfcInvocationContext context)
    {
        _logger.LogInformation(
            "SAP RFC invocation succeeded. ConfigId={ConfigId}, Function={Function}, Elapsed={ElapsedMs}ms",
            context.ConfigId,
            context.FunctionName,
            context.Elapsed.TotalMilliseconds);
    }

    public void InvocationFailed(RfcInvocationContext context, Exception exception)
    {
        _logger.LogError(
            exception,
            "SAP RFC invocation failed. ConfigId={ConfigId}, Function={Function}, Elapsed={ElapsedMs}ms",
            context.ConfigId,
            context.FunctionName,
            context.Elapsed.TotalMilliseconds);
    }
}

Register the monitor before or after AddRfcClient:

using RfcClient.Abstractions;

builder.Services.AddSingleton<IRfcConnectionMonitor, LoggingRfcConnectionMonitor>();
builder.Services.AddRfcClient(builder.Configuration);

Do not log passwords or full connection strings.

Runtime Files

The project expects SAP NCo runtime files under the libs folder:

libs/cpc4n.dll
libs/ijwhost.dll
libs/sapnco.dll
libs/sapnco_utils.dll

During build, these files are copied to the output root directory alongside RfcClient.dll. They are also included in the NuGet package under lib/net10.0/.

Configuration options: the library exposes two timing options in RfcOptions:

  • CleanupInterval (default 00:05:00): how often the client checks for idle destinations to cleanup.
  • DestinationIdleTimeout (default 00:10:00): how long a destination can stay unused before being removed from the cache.

You can set these in appsettings.json or via code when registering the services.

XML Documentation

The library generates an XML documentation file (RfcClient.xml) alongside the assembly in the build output. IDEs such as Visual Studio and JetBrains Rider automatically pick it up to provide inline Chinese and English descriptions for public types and members.

Build And Pack

dotnet build .\RfcClient.sln
dotnet pack .\RfcClient.csproj -c Release

The package is generated under:

bin/Release/RfcClient.0.1.0.nupkg
Product Compatible and additional computed target framework versions.
.NET 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
1.0.12 87 8/5/2026
1.0.11 78 7/24/2026
1.0.10 74 7/24/2026
1.0.9 77 7/22/2026
1.0.8 83 7/21/2026
1.0.7 79 7/20/2026
1.0.6 75 7/15/2026
1.0.5 81 7/15/2026
1.0.4 73 7/15/2026
1.0.3 81 7/14/2026
1.0.2 84 7/13/2026
1.0.1 75 7/13/2026
1.0.0 88 7/11/2026
0.1.1 89 7/9/2026
0.1.0 84 7/9/2026