Compartir vía


Recepción de llamadas RFC entrantes en SAP mediante el modelo de servicio WCF

El adaptador de Microsoft BizTalk para mySAP Business Suite puede actuar como un servidor RFC para recibir RFC invocado por un sistema SAP.

Para recibir las RFC de entrada en el modelo de servicio WCF, debe hacer lo siguiente:

  • Asegúrese de que existe un destino RFC en el sistema SAP.

  • Asegúrese de que la RFC está definida en el sistema SAP.

  • Genere un contrato de servicio WCF (interfaz) para la operación RFC a partir de los metadatos expuestos por el adaptador. Para ello, use el complemento Agregar referencia del servicio adaptador de Visual Studio o la Herramienta de utilidad de metadatos ServiceModel (svcutil.exe).

  • Implemente un servicio WCF desde esta interfaz. Los métodos del servicio WCF contienen la lógica necesaria para procesar la RFC y devolver una respuesta al adaptador (y, por tanto, el sistema SAP).

  • Hospede este servicio WCF mediante un host de servicio (System.ServiceModel.ServiceHost).

    En las secciones siguientes se muestra cómo recibir RFC del sistema SAP mediante el adaptador de SAP.

Cómo configurar el sistema SAP para enviar una RFC al adaptador de SAP

Para poder enviar un RFC desde el sistema SAP al adaptador de SAP, debe asegurarse de que lo siguiente es true en el sistema SAP:

  • Debe existir un destino RFC para el adaptador de SAP. El adaptador de SAP se registra con un destino RFC para recibir RFC del sistema SAP. Los parámetros se proporcionan en el URI de conexión de SAP, como el host de puerta de enlace de SAP, el servicio de puerta de enlace de SAP y el identificador de programa de SAP que usa el adaptador para registrarse. Para obtener información sobre cómo configurar un destino RFC en SAP, consulte Creación de un RFC, destino RFC y envío de un RFC desde el sistema SAP.

  • La RFC debe definirse en el sistema SAP. Debe crear un módulo de función que defina la RFC en el sistema SAP. El adaptador de SAP usa la definición de RFC en el sistema SAP para recuperar metadatos sobre la RFC (tanto en tiempo de diseño como en tiempo de ejecución). Para obtener más información, consulte Creación de una RFC en un sistema SAP.

    Nota

    Debe definir la RFC en el sistema SAP; sin embargo, implemente la RFC en el código de cliente del adaptador. La RFC debe definirse en el sistema SAP para que el adaptador pueda recuperar los metadatos de la RFC.

    A continuación se muestra un ejemplo del código fuente en el sistema SAP para una RFC que agrega dos enteros y devuelve su resultado. El código simplemente llama a la RFC a través de un destino especificado. El código de cliente del adaptador de SAP realiza la implementación de la función.

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.  

Contrato de servicio WCF para un RFC

Use el complemento Agregar referencia del servicio adaptador de Visual Studio o la Herramienta de utilidad de metadatos serviceModel (svcutil.exe) para generar un contrato de servicio WCF para las RFC que desea recibir del sistema SAP. En las secciones siguientes se muestran las clases de código administrado y las interfaces generadas para la operación de Z_RFC_MKD_ADD.

La interfaz Rfc (contrato de servicio WCF)

El adaptador de SAP muestra todas las operaciones RFC en un único contrato de servicio, "Rfc". Esto significa que se crea una única interfaz, Rfc, para todas las operaciones rfC que desea recibir. Cada operación RFC de destino se representa como un método de esta interfaz. Cada método toma un único parámetro, que representa el contrato de mensaje para el mensaje de solicitud de la operación y devuelve un objeto , que representa el contrato de mensaje del mensaje de respuesta de la operación.

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

Mensajes de solicitud y respuesta

Cada operación RFC toma un parámetro que representa el mensaje de solicitud y devuelve un objeto que representa el mensaje de respuesta. Las propiedades del mensaje de solicitud contienen los parámetros IMPORT y (input) CHANGING del RFC. Las propiedades del mensaje de respuesta contienen los parámetros EXPORT y (output) CHANGING para la operación.

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

El servicio WCF generado

El complemento Add Adapter Service Reference también genera un servicio WCF que implementa el contrato de servicio WCF (Rfc). Los métodos de esta clase son auxiliares. Esta clase se genera en un archivo independiente. Puede implementar el código directamente en los métodos de esta clase.

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

Creación de una aplicación de servidor RFC

Para recibir RFC del sistema SAP mediante el modelo de servicio WCF, puede seguir los pasos descritos en Información general del modelo de servicio WCF con el adaptador de SAP. Asegúrese de especificar "Rfc" para el contrato de servicio al agregar el punto de conexión de servicio (paso 6 del procedimiento para crear e implementar un servicio WCF).

En el código siguiente se muestra un ejemplo completo de cómo recibir el Z_RFC_MKD_RFC de un sistema SAP mediante el adaptador de SAP. Este RFC toma dos parámetros enteros y devuelve el resultado 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);  
                }  
            }  
        }  
    }  
}  

Consulte también

Desarrollar aplicaciones con el modelo de servicio WCF
Esquemas de mensaje para operaciones de RFC