Coder Social home page Coder Social logo

yanco's Introduction

YaNco - Yet another .NET Connector

.NET Connector for SAP Netweaver RFC

Stable Latest
NuGet stable NuGet pre

Description

This library provides an alternative SAP .NET Connector based on the SAP NetWeaver RFC Library.

Features:

  • thin, modern layer above native SAP Netweaver RFC SDK
  • DI container friendly API
  • Functional programming friendly API (using Language.Ext)
  • ABAP callbacks support (not possible with sapnco, see SAP note 2297083).

Platforms & Prerequisites

.NET

The library requires .NET Framework >= 4.7.1 or .NET Core 2.0 or higher.

Supported platforms: Windows, Linux and MacOS.

Windows: C++ Runtimes

On Windows the Visual Studio 2013 (VC++ 12.0) runtime library has to be installed. Library can be downloaded here: https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads

SAP Netweaver RFC SDK

To use and build YaNco you need to obtain SAP NW RFC SDK 750 from SAP Support Portal.

A prerequisite to download is having a customer or partner account on SAP Support Portal and if you are SAP employee please check SAP Note 1037575 - Software download authorizations for SAP employees.

You can automate the download of the SAP NW RFC SDK with the dotnet tool sapnwrfc-download.
See https://www.dbosoft.eu/en-us/blog/sap-netweaver-rfc-sdk-download-tool for details.

SAP NW RFC SDK 750 is fully backwards compatible, supporting all NetWeaver systems, from today, down to release R/3 4.6C. You can therefore always use the newest version released on SAP Support Portal and connect to older systems as well.

Getting started

The easiest way to get started is by installing the available NuGet package. Take a look at the Using section learning how to configure and use YaNco. Go to the Build section to find out how to build YaNco.

Using

In order to call remote enabled ABAP function module (ABAP RFM), first a connection must be opened. The connection settings have to be build from a string/string dictionary, for example from a ConfigurationBuilder.

var configurationBuilder =
    new ConfigurationBuilder();

configurationBuilder.AddUserSecrets<Program>();
var config = configurationBuilder.Build();

var settings = new Dictionary<string, string>
{
    {"ashost", config["saprfc:ashost"]},
    {"sysnr", config["saprfc:sysnr"]},
    {"client", config["saprfc:client"]},
    {"user", config["saprfc:username"]},
    {"passwd", config["saprfc:password"]},
    {"lang", "EN"}

};

With these settings you can now create a ConnectionBuilder instance and use it to open a RfcContext.

var connectionBuilder = new ConnectionBuilder(settings);
var connFunc = connectionBuilder.Build();

using (var context = new RfcContext(connFunc))
{
   ...

}

The connection builders Build() method returns a function that can be reused to open additional connections. The RfcContext will do that internally in case the connection breaks.

Under the hood the ConnectionBuilder also creates also a RfcRuntime instance. The RfcRuntime is a low level API that you will typical never use directly. But you can customize it on the ConnectionBuilder with the ConfigureRuntime() method. For example to add a logger:

var connectionBuilder = new ConnectionBuilder(connFunc)
    .ConfigureRuntime(c => 
        c.WithLogger(new MyLogger()));

Calling ABAP Function Modules

We provide a extension method on the RFCContext that supports a syntax similar to the ABAP call function command, except that it is using function callbacks to pass or retrieve data:

  • IMPORTING parameters are passed in the Input function
  • EXPORTING parameters are retured in the Output function
  • CHANGING and TABLES parameters can be used in both functions
using (var context = new RfcContext(connFunc))
{
    await context.CallFunction("DDIF_FIELDLABEL_GET",
            Input: f => f
                .SetField("TABNAME", "USR01")
                .SetField("FIELDNAME", "BNAME"),
            Output: f => f
                .GetField<string>("LABEL"))

        // this is from language.ext to extract the value from a either
        .Match(r => Console.WriteLine($"Result: {r}"), // should return: User Name
            l => Console.WriteLine($"Error: {l.Message}"));
}

The Result of the function is a Either<L,R> type (see language.ext Either left right monad). The Match call at the end either writes the result (right value) or a rfc error (left value).

Structures

Structures can be set or retrieved the same way. Another example extracting company code details (you may have to change the company code if you try this example):

using (var context = new RfcContext(connFunc))
{
    await context.CallFunction("BAPI_COMPANYCODE_GETDETAIL",
            Input: f => f
                .SetField("COMPANYCODEID", "1000"),
            Output: f => f
                .MapStructure("COMPANYCODE_DETAIL", s=> s
                    .GetField<string>("COMP_NAME"))
        )
        .Match(r => Console.WriteLine($"Result: {r}"),
            l => Console.WriteLine($"Error: {l.Message}"));

}

Alternatively, you can also use a LINQ syntax:

using (var context = new RfcContext(connFunc))
{
    await context.CallFunction("BAPI_COMPANYCODE_GETDETAIL",
        Input: f => f
            .SetField("COMPANYCODEID", "1000"),
        Output: f => f
            .MapStructure("COMPANYCODE_DETAIL", s =>
                from name in s.GetField<string>("COMP_NAME")
                select name
            ))

            .Match(r => Console.WriteLine($"Result: {r}"),
                l => Console.WriteLine($"Error: {l.Message}"));

}

Especially for complex structures, the LINQ syntax is often easier to read.

Tables

Getting table results is possible by iterating over the table rows to retrieve the table structures. Here an example to extract all company code name and descriptions:

using (var context = new RfcContext(connFunc))
{
    await context.CallFunction("BAPI_COMPANYCODE_GETLIST",
            Output: f => f
                .MapTable("COMPANYCODE_LIST", s =>
                    from code in s.GetField<string>("COMP_CODE")
                    from name in s.GetField<string>("COMP_NAME")
                    select (code, name)))
        .Match(
            r =>
            {
                foreach (var (code, name) in r)
                {
                    Console.WriteLine($"{code}\t{name}");
                }
            },
            l => Console.WriteLine($"Error: {l.Message}"));

}

Build

We use Visual Studio 2019 for building.

As explained above you have to obtain SAP NW RFC Library 750 from SAP Support Portal. But the SDK is only required to run test applications, so just building works without the RFC SDK.

If you download the SDK use the x64 version and copy to DLLs from lib folder to a directory in your PATH environment variable.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

  • Frank Wagner - Initial work - fw2568

See also the list of contributors who participated in this project.

Commercial support

The creators of YaNco, dbosoft, offer professional support plans which we strongly recommend for any organisations using YaNco on a commercial basis.

They includes:

  • Prioritised resolution of any bugs. If you find a bug that’s blocking you, we’ll prioritise it and release a hot fix as soon as it’s ready.
  • Prioritised resolution and escalation of issues. If there’s a possible issue or question, we’ll prioritise dealing with it.
  • Prioritised feature requests: Get new features that are important to you added first.
  • Personalised support and guidance via email, telephone or video. Speak to one of our team for advice and best practices on how to best manage deployments.
  • Discounts on training and coaching services

License

This project is licensed under the MIT License - see the LICENSE file for details

Trademark notice

SAP, Netweaver are trademarks of SAP SE

yanco's People

Contributors

dbosoft-fw avatar dependabot[bot] avatar fw2568 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.