Freigeben über


Empfangen eingehender RFC-Aufrufe in SAP mithilfe des WCF-Dienstmodells

Der Microsoft BizTalk-Adapter für mySAP Business Suite kann als RFC-Server fungieren, um RFCs zu empfangen, die von einem SAP-System aufgerufen werden.

Um die eingehenden RFCs im WCF-Dienstmodell zu empfangen, müssen Sie:

  • Stellen Sie sicher, dass im SAP-System ein RFC-Ziel vorhanden ist.

  • Stellen Sie sicher, dass der RFC im SAP-System definiert ist.

  • Generieren Sie einen WCF-Dienstvertrag (Schnittstelle) für den RFC-Vorgang aus den Metadaten, die vom Adapter verfügbar gemacht werden. Verwenden Sie hierzu das Visual Studio-Plug-In Adapterdienstverweis hinzufügen oder das ServiceModel Metadata Utility Tool (svcutil.exe).

  • Implementieren Sie einen WCF-Dienst über diese Schnittstelle. Die Methoden des WCF-Diensts enthalten die Logik, die erforderlich ist, um den RFC zu verarbeiten und eine Antwort an den Adapter (und damit das SAP-System) zurückzugeben.

  • Hosten Sie diesen WCF-Dienst mithilfe eines Diensthosts (System.ServiceModel.ServiceHost).

    In den folgenden Abschnitten wird gezeigt, wie Sie RFCs vom SAP-System mithilfe des SAP-Adapters empfangen.

Einrichten des SAP-Systems zum Senden eines RFC an den SAP-Adapter

Bevor Sie einen RFC vom SAP-System an den SAP-Adapter senden können, müssen Sie sicherstellen, dass Folgendes auf dem SAP-System zutrifft:

  • Ein RFC-Ziel für den SAP-Adapter muss vorhanden sein. Der SAP-Adapter registriert sich selbst bei einem RFC-Ziel, um RFCs vom SAP-System zu empfangen. Sie geben Parameter im SAP-Verbindungs-URI an, z. B. den SAP-Gatewayhost, den SAP-Gatewaydienst und die SAP-Programm-ID, die der Adapter zum Registrieren verwendet. Informationen zum Einrichten eines RFC-Ziels in SAP finden Sie unter Erstellen eines RFC- und RFC-Ziels und Senden eines RFC aus dem SAP-System.

  • Der RFC muss im SAP-System definiert werden. Sie müssen ein Funktionsmodul erstellen, das den RFC im SAP-System definiert. Der SAP-Adapter verwendet die RFC-Definition auf dem SAP-System, um Metadaten zum RFC abzurufen (sowohl zur Entwurfszeit als auch zur Laufzeit). Weitere Informationen finden Sie unter Erstellen eines RFC in einem SAP-System.

    Hinweis

    Sie müssen den RFC im SAP-System definieren. Sie implementieren jedoch rfc in Ihrem Adapterclientcode. Der RFC muss im SAP-System definiert werden, damit der Adapter Metadaten für den RFC abrufen kann.

    Im Folgenden finden Sie ein Beispiel für den Quellcode im SAP-System für einen RFC, der zwei ganze Zahlen hinzufügt und deren Ergebnis zurückgibt. Der Code ruft den RFC lediglich über ein angegebenes Ziel auf. Die Implementierung der Funktion erfolgt durch den Clientcode des SAP-Adapters.

FUNCTION Z_RFC_SAMPLE_ADD.  
*"---------------------------------------------------------------------*"*"Local interface:  
*"  IMPORTING  
*"     VALUE(X) TYPE  INT4  
*"     VALUE(Y) TYPE  INT4  
*"     VALUE(DEST) TYPE  CHAR20 DEFAULT 'SAPADAPTER'  
*"  EXPORTING  
*"     VALUE(RESULT) TYPE  INT4  
*"---------------------------------------------------------------------CALL FUNCTION 'Z_RFC_MKD_ADD' DESTINATION DEST  
  EXPORTING X = X  
            Y = Y  
  IMPORTING RESULT = RESULT.  
  
ENDFUNCTION.  

Der WCF-Dienstvertrag für einen RFC

Sie verwenden das Visual Studio-Plug-In Adapterdienstverweis hinzufügen oder das ServiceModel Metadata Utility Tool (svcutil.exe), um einen WCF-Dienstvertrag für die RFCs zu generieren, die Sie vom SAP-System erhalten möchten. Die folgenden Abschnitte zeigen die verwalteten Codeklassen und Schnittstellen, die für den Z_RFC_MKD_ADD-Vorgang generiert wurden.

Rfc-Schnittstelle (WCF-Dienstvertrag)

Der SAP-Adapter zeigt alle RFC-Vorgänge unter einem einzelnen Dienstvertrag an, "Rfc". Dies bedeutet, dass eine einzelne Schnittstelle , Rfc, für alle RFC-Vorgänge erstellt wird, die Sie erhalten möchten. Jeder RFC-Zielvorgang wird als Methode dieser Schnittstelle dargestellt. Jede Methode verwendet einen einzelnen Parameter, der den Nachrichtenvertrag für die Anforderungsnachricht des Vorgangs darstellt, und gibt ein -Objekt zurück, das den Nachrichtenvertrag der Antwortnachricht des Vorgangs darstellt.

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]  
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.LobServices.Sap/2007/03/", ConfigurationName="Rfc")]  
public interface Rfc {  
  
    // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.Sap/2007/03/Rfc/) of message Z_RFC_MKD_ADDRequest does not match the default value (http://Microsoft.LobServices.Sap/2007/03/)  
    [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.LobServices.Sap/2007/03/Rfc/Z_RFC_MKD_ADD", ReplyAction="http://Microsoft.LobServices.Sap/2007/03/Rfc/Z_RFC_MKD_ADD/response")]  
    Z_RFC_MKD_ADDResponse Z_RFC_MKD_ADD(Z_RFC_MKD_ADDRequest request);  
}  
  

Anforderungs- und Antwortnachrichten

Jeder RFC-Vorgang verwendet einen Parameter, der die Anforderungsnachricht darstellt, und gibt ein Objekt zurück, das die Antwortnachricht darstellt. Die Eigenschaften der Anforderungsnachricht enthalten die PARAMETER IMPORT und (Eingabe) CHANGING des RFC. Die Eigenschaften der Antwortnachricht enthalten die PARAMETER EXPORT und (Ausgabe) CHANGING für den Vorgang.

[System.Diagnostics.DebuggerStepThroughAttribute()]  
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]  
[System.ServiceModel.MessageContractAttribute(WrapperName="Z_RFC_MKD_ADD", WrapperNamespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", IsWrapped=true)]  
public partial class Z_RFC_MKD_ADDRequest {  
  
    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", Order=0)]  
    public string DEST;  
  
    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", Order=1)]  
    public System.Nullable<int> X;  
  
    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", Order=2)]  
    public System.Nullable<int> Y;  
  
    public Z_RFC_MKD_ADDRequest() {  
    }  
  
    public Z_RFC_MKD_ADDRequest(string DEST, System.Nullable<int> X, System.Nullable<int> Y) {  
        this.DEST = DEST;  
        this.X = X;  
        this.Y = Y;  
    }  
}  
  
[System.Diagnostics.DebuggerStepThroughAttribute()]  
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]  
[System.ServiceModel.MessageContractAttribute(WrapperName="Z_RFC_MKD_ADDResponse", WrapperNamespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", IsWrapped=true)]  
public partial class Z_RFC_MKD_ADDResponse {  
  
    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/", Order=0)]  
    public int RESULT;  
  
    public Z_RFC_MKD_ADDResponse() {  
    }  
  
    public Z_RFC_MKD_ADDResponse(int RESULT) {  
        this.RESULT = RESULT;  
    }  
}  

Der generierte WCF-Dienst

Das Add Adapter Service Reference Plug-In generiert auch einen WCF-Dienst, der den WCF-Dienstvertrag (Rfc) implementiert. Die Methoden dieser Klasse sind stubbed. Diese Klasse wird in einer separaten Datei generiert. Sie können Ihren Code direkt in den Methoden dieser Klasse implementieren.

namespace SAPBindingNamespace {  
  
    public class SAPBindingService : Rfc {  
  
        // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.Sap/2007/03/Rfc/) of message Z_RFC_MKD_ADDRequest does not match the default value (http://Microsoft.LobServices.Sap/2007/03/)  
        public virtual Z_RFC_MKD_ADDResponse Z_RFC_MKD_ADD(Z_RFC_MKD_ADDRequest request) {  
            throw new System.NotImplementedException("The method or operation is not implemented.");  
        }  
    }  
}  

Erstellen einer RFC-Serveranwendung

Um RFCs vom SAP-System mithilfe des WCF-Dienstmodells zu empfangen, können Sie die Schritte unter Übersicht über das WCF-Dienstmodell mit dem SAP-Adapter ausführen. Achten Sie darauf, dass Sie "Rfc" für den Dienstvertrag angeben, wenn Sie den Dienstendpunkt hinzufügen (Schritt 6 des Verfahrens zum Erstellen und Implementieren eines WCF-Diensts).

Der folgende Code zeigt ein vollständiges Beispiel für das Empfangen der Z_RFC_MKD_RFC von einem SAP-System mithilfe des SAP-Adapters. Dieser RFC akzeptiert zwei ganzzahlige Parameter und gibt das Ergebnis an das SAP-System zurück.

using System;  
using System.Collections.Generic;  
using System.Text;  
  
// Add WCF, WCF LOB Adapter SDK, and SAP adapter namepaces  
using System.ServiceModel;  
using Microsoft.Adapters.SAP;  
using Microsoft.ServiceModel.Channels;  
  
// Include this namespace for the WCF LOB Adapter SDK and SAP adapter exceptions  
using Microsoft.ServiceModel.Channels.Common;  
  
namespace SapRfcServerSM  
{  
    // Implement a WCF service callback class by sub-classing the generated service callback class (SAPBindingService).  
    // You must annotate this class with the InstanceContextMode.Single ServiceBehavior  
    // If you implement your code in SAPBindingService.cs be sure to annotate the SAPBindingService class  
    // The callback method should return a Z_RFC_MKD_ADDResponse to indicate successful processing  
    // or throw an exception to indicate an error.  
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,UseSynchronizationContext = false)]  
    class RfcServerClass : SAPBindingNamespace.SAPBindingService  
    {  
  
        public override Z_RFC_MKD_ADDResponse Z_RFC_MKD_ADD(Z_RFC_MKD_ADDRequest request)  
        {  
            // If either parameter is null, throw an exception   
            if (request.X == null || request.Y == null)  
                throw new System.ArgumentNullException();  
  
            int result = (int) (request.X + request.Y);  
  
            Console.WriteLine("\nRfc Received");  
            Console.WriteLine("X =\t\t" + request.X.ToString());  
            Console.WriteLine("Y =\t\t" + request.Y.ToString());  
            Console.WriteLine("Result =\t" + result);  
            Console.WriteLine("\nHit <RETURN> to end");  
  
            return new Z_RFC_MKD_ADDResponse(result);  
        }  
  
    }  
  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Listener connection for the service URI -- the connection URI must contain credentials  
            Uri serviceUri = new Uri("sap://User=YourUserName;Passwd=YourPassword;Client=800;Lang=EN;@a/ADAPSAP47/00?ListenerGwServ=SAPGW00&ListenerGwHost=ADAPSAP47&ListenerProgramId=ADDER");  
  
            // The baseUri cannot contain userinfoparams or query_string parameters  
            Uri[] baseUri = new Uri[] { new Uri("sap://a/ADAPSAP47/00") };  
  
            Console.WriteLine("RFC server sample started");  
  
            // create service instance  
            RfcServerClass rfcServerInstance = new RfcServerClass();  
  
            try  
            {  
                Console.WriteLine("Initializing service host -- please wait");  
                // Create and initialize a service host  
                using (ServiceHost srvHost = new ServiceHost(rfcServerInstance, baseUri))  
                {  
  
                    // Add service endpoint   
                    // Specify AcceptCredentalsInUri=true for the binding  
                    // NOTE: The contract for the service endpoint is "Rfc".  
                    //       This is the generated WCF service callback interface (see SAPBindingInterface.cs).  
                    SAPBinding binding = new SAPBinding();  
                    binding.AcceptCredentialsInUri = true;  
                    srvHost.AddServiceEndpoint("Rfc", binding, serviceUri);  
                    srvHost.Open();  
  
                    Console.WriteLine("\nReady to receive Z_RFC_MKD_ADD RFC");  
                    Console.WriteLine("Hit <RETURN> to end");  
  
                    // Wait to receive request  
                    Console.ReadLine();  
                }  
            }  
            catch (ConnectionException cex)  
            {  
                Console.WriteLine("Exception occurred connecting to the SAP system");  
                Console.WriteLine(cex.InnerException.Message);  
            }  
            catch (TargetSystemException tex)  
            {  
                Console.WriteLine("Exception occurred on the SAP system");  
                Console.WriteLine(tex.InnerException.Message);  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Exception is: " + ex.Message);  
                if (ex.InnerException != null)  
                {  
                    Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);  
                }  
            }  
        }  
    }  
}  

Weitere Informationen

Entwickeln von Anwendungen mithilfe des WCF-Dienstmodells
Nachrichtenschemas für RFC-Vorgänge