Condividi tramite


Ricevere chiamate RFC in ingresso in SAP usando il modello di servizio WCF

L'adapter Microsoft BizTalk per mySAP Business Suite può fungere da server RFC per ricevere le RFC richiamate da un sistema SAP.

Per ricevere le RFC in ingresso nel modello di servizio WCF, è necessario:

  • Verificare che nel sistema SAP esista una destinazione RFC.

  • Assicurarsi che la RFC sia definita nel sistema SAP.

  • Generare un contratto di servizio WCF (interfaccia) per l'operazione RFC dai metadati esposti dall'adattatore. A tale scopo, usare il plug-in Add Adapter Service Reference di Visual Studio o lo strumento serviceModel Metadata Utility (svcutil.exe).

  • Implementare un servizio WCF da questa interfaccia. I metodi del servizio WCF contengono la logica necessaria per elaborare la RFC e restituire una risposta all'adapter (e quindi il sistema SAP).

  • Ospitare questo servizio WCF usando un host del servizio (System.ServiceModel.ServiceHost).

    Le sezioni seguenti illustrano come ricevere le RFC dal sistema SAP usando l'adattatore SAP.

Come configurare il sistema SAP per inviare un RFC all'adapter SAP

Prima di poter inviare un RFC dal sistema SAP all'adattatore SAP, è necessario assicurarsi che nel sistema SAP siano vere le condizioni seguenti:

  • Deve esistere una destinazione RFC per l'adapter SAP. L'adattatore SAP si registra con una destinazione RFC per ricevere le RFC dal sistema SAP. Specificare i parametri nell'URI di connessione SAP, ad esempio l'host del gateway SAP, il servizio GATEWAY SAP e l'ID programma SAP usato dall'adattatore per registrare se stesso. Per informazioni su come configurare una destinazione RFC in SAP, vedere Creare una destinazione RFC, RFC e inviare un RFC dal sistema SAP.

  • La RFC deve essere definita nel sistema SAP. È necessario creare un modulo di funzione che definisce la RFC nel sistema SAP. L'adattatore SAP usa la definizione RFC nel sistema SAP per recuperare i metadati relativi alla RFC (sia in fase di progettazione che in fase di esecuzione). Per altre informazioni, vedere Creazione di un RFC in un sistema SAP.

    Nota

    È necessario definire la RFC nel sistema SAP; tuttavia si implementa la RFC nel codice client dell'adattatore. Il RFC deve essere definito nel sistema SAP in modo che l'adattatore possa recuperare i metadati per la RFC.

    Di seguito è riportato un esempio del codice sorgente nel sistema SAP per un RFC che aggiunge due numeri interi e ne restituisce il risultato. Il codice chiama semplicemente il RFC tramite una destinazione specificata. L'implementazione della funzione viene eseguita dal codice client dell'adapter SAP.

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.  

Contratto di servizio WCF per un RFC

Usare il plug-in Add Adapter Service Reference di Visual Studio o lo Strumento utilità metadati ServiceModel (svcutil.exe) per generare un contratto di servizio WCF per le RFC che si desidera ricevere dal sistema SAP. Le sezioni seguenti illustrano le classi di codice gestito e le interfacce generate per l'operazione di Z_RFC_MKD_ADD.

Interfaccia Rfc (contratto di servizio WCF)

L'adattatore SAP espone tutte le operazioni RFC in un singolo contratto di servizio, "Rfc". Ciò significa che viene creata una singola interfaccia, Rfc, per tutte le operazioni RFC che si desidera ricevere. Ogni operazione RFC di destinazione è rappresentata come metodo di questa interfaccia. Ogni metodo accetta un singolo parametro, che rappresenta il contratto di messaggio per il messaggio di richiesta dell'operazione e restituisce un oggetto , che rappresenta il contratto di messaggio del messaggio di risposta dell'operazione.

[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);  
}  
  

Messaggi di richiesta e risposta

Ogni operazione RFC accetta un parametro che rappresenta il messaggio di richiesta e restituisce un oggetto che rappresenta il messaggio di risposta. Le proprietà del messaggio di richiesta contengono i parametri IMPORT e (input) CHANGING dell'RFC. Le proprietà del messaggio di risposta contengono i parametri EXPORT e (output) CHANGING per l'operazione.

[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;  
    }  
}  

Servizio WCF generato

Il plug-in Add Adapter Service Reference genera anche un servizio WCF che implementa il contratto di servizio WCF (Rfc). I metodi di questa classe sono stub. Questa classe viene generata in un file separato. È possibile implementare il codice direttamente nei metodi di questa classe.

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.");  
        }  
    }  
}  

Come creare un'applicazione server RFC

Per ricevere RFC dal sistema SAP usando il modello di servizio WCF, è possibile seguire la procedura descritta in Panoramica del modello di servizio WCF con l'adapter SAP. Assicurarsi di specificare "Rfc" per il contratto di servizio quando si aggiunge l'endpoint di servizio (passaggio 6 della procedura per la creazione e l'implementazione di un servizio WCF).

Il codice seguente illustra un esempio completo di come ricevere il Z_RFC_MKD_RFC da un sistema SAP usando l'adattatore SAP. Questo RFC accetta due parametri integer e restituisce il risultato al sistema SAP.

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

Vedere anche

Sviluppare applicazioni tramite il modello di servizio WCF
Schemi di messaggio per operazioni RFC