Business APIs (BAPI) are defined in the Business Object Repository (BOR) as methods of SAP business object types or SAP interface types, and are implemented as function modules
in the ABAP code.
Each BAPI returns status information about its execution in a complex parameter named
Return in its output message.
This parameter reports exception messages or success messages back to the calling program.
BAPIs themselves must not trigger any messages (such as MESSAGE xnnn) in the
ABAP coding. In particular they must not generate terminations or display dialog boxes.
Instead, all messages must be intercepted internally and reported back to the calling program in the Return parameter.
If, in at least one of the entries of Return parameter, the field Type is filled with A (abort) or E (error), a database rollback is
executed in the standard programming model, that is, all tasks performed since the last COMMIT WORK are canceled.
In the past the only way to access a BAPI from .NET was to make RFC calls to the function modules on which the BAPI is based using the
Connector for Microsoft .NET+ (NCo). However SAP NCo version 1.x and 2.x will not install inside
Visual Studio 2005. Instead developers have to build components in Visual Studio 2003 and use these in Visual Studio 2005 projects as described in the document
Using SAP Connector for MS .NET (NCO) in Microsoft Visual Studio 2005.
As an alternative approach to RFC based communication made
available by the SAP connector for Microsoft .NET it is strongly recommended by
SAP to use Web Services as the de-facto standard for interoperability between
software (systems) of heterogeneous implementations. (see
SAP Note 943349 ). SAP systems that are based on the SAP NetWeaver Application Server allow for a Web
service based communication since it is possible to create a Web service for every BAPI using the
Web Service Creation Wizard.
If one of the error conditions mentioned above does occur when calling a BAPI one would like to throw an exception in
the calling .NET program.
If a BAPI is called using the SAP NCo the mechanism of throwing a BAPI specific .NET exception can be activated during design time.
The .NET proxy that is generated by the NCo then contains the .NET coding that performs this task. In contrast to a proxy generated by the NCo a Web service
proxy that is generated from a Web reference does not contain coding that throws
In my blog I would therefore like to introduce a set of C#-classes that can be used to throw .NET exceptions in the calling .NET Web services client
thus allowing to have the same functionality of exception handling as it has
been available with the NCo.
“Checker” class SAP.NetWeaver.Bapi.BapiException.BapiRetCheck
Since the coding of the Web service proxy does not throw a .NET execption a new
checker class SAP.NetWeaver.Bapi.BapiException had to be implemented that
performs a check for the Return parameter in the calling .NET client. By just adding one line of code
an exception of type SAP.NetWeaver.BAPI.BapiException will be thrown if at least
in one of the entries of
the Return parameter
(here: bapiReturn), the field
Type is filled with A (abort) or E (error).
BAPI Return Parameter
The export parameter Return can be implemented in a BAPI in two different ways:
- As a structure, whereby it is defined in the function module as an export parameter.
- As a table, whereby it is defined in the function module as a table parameter
The Return parameter may thereby be based on one the following reference structures:
While BAPIRET2 is used in new BAPIs the structures BAPIRET1, BAPIRETURN and BAPIRETURN1 may still partly
be used in old BAPIs. The structures BAPIRET1 and BAPIRETURN1 consist of the same fields as the BAPIRET2 structure excluding the fields PARAMETER, ROW, FIELD and SYSTEM. The structure BAPIRETURN consists of the same fields as BAPIRETURN1 and BAPIRET1 excluding the field NUMBER that is used to store the numeric value of the BAPI Return code. The BAPIRETURN structure therefore uses the field CODE instead.
Since the Return parameter may be based on one of the four mentioned reference structures and because it may be returned as a structure or a table a developer could be confronted with up to eight different options how a BAPI returns its Return code.
It was therefore one of the design goals to use a generic coding to check for the BAPI Return codes.
The .NET Framework allows developers to
discover information about types included in their programs or in other
assemblies. This is referred to as Reflection and it is provided through a set
of .NET base classes included in the System.Reflection namespace. This
sample uses the System.Reflection namespace and some of the main classes
to gather information on the various types that may be used by a Return code
that is returned by the Web service proxy.</p>
How to use the Checker Class
Before digging into the coding of the checker class we first want to have a
look how it can be used. The coding that contains the class declarations resides in one code File BapiRet.cs
which can thus easily be added to any existing project.</p>
Step 1: Add BapiException.cs to the project
- In Solution Explorer, select a
- On the Project menu, select Add
In the Add Existing dialog box,
locate and select the the file BapiException.cs that you want to add.</li>
Step 2: Add using directive for the Namespace SAP.NetWeaver.Bapi
Add the following using directive to your coding:
Step 3: Create Checker object
Now we have to create an instance of the checker object. To do this we add
the following line to the coding where the other varaibles are declared.
// Create a checker object
BapiRetCheck checker = new BapiRetCheck();
Step 4: Perform check
As shown in the coding of a C# Web services command line
application below we just have to add one single line of code after the call of the
Web service proxy.
If the Return parameter is defined as a structure the Web service call will look like
If the Return parameter is defined as a table the Web service call will look like
Step 5: Add exception handling
We now have to add the exception handling.for the BAPI Exceptions that might be
raised. It is recommended to have at least two catch blocks.
The first catch statement is for the SAP specific exceptions of type +
SAP.NetWeaver.Bapi.BapiException +and the second for others (generic),
for example errors from the runtime or other resources.
If the Return parameter does not contain an error message the content of
the Return parameter can also be retrieved using the property ReturnTable
of the checker object.
Example: C# Web services client commandline application
The sample code consists out of three classes that are using the namespace +
SAP.NetWeaver.Bapi+. The class BapiRetCheck is used to check the
Return Parameter of a BAPI that is called via Web services. The class ReturnParameters
is used as a generic storage for the content that is retrieved from the Return
parameter. The class BapiException is derived from System.Exception.
If in at least one of the entries of Return parameter, the field Type is filled with A (abort) or E (error)
an exception of type SAP.NetWeaver.Bapi.BapiException.</p>
The method check takes the Return parameter as an argument. </span>The
Return parameter is passed as an object called bapiReturn. If the+
Return+ parameter in the BAPI is implemented as a table bapiReturn is
As a first step it is checked whether the object bapiReturn is an array. If
the object bapiReturn is an array of objects a loop is performed to iterate
through all members. Check then passes the single object(s) to the private method +
PerformCheck first checks whether bapiReturn has has either
the structure of BAPIRET2
, BAPIRET1 BAPIRETURN or BAPIRETURN1. If the check went OK the content of the
fields of the Return parameter are assigned to an ReturnParameters object
PerformCheck+ checks whether the property +Type +of +bapiReturnParameters
+contains “A” or “E” which would raise an exception of type +BapiException.
+Otherwise the content is added as an additional item to the property ReturnTable..</p>
if ((bapiReturnParameters.Type == “E”) || (bapiReturnParameters.Type ==
throw new BapiException(bapiReturnParameters); // in case if
real error otherwise just return
The class BapiException is derived from System.Exception.
If this exception is raised it gets the the
entry of the Return parameter where the field Type filled with A (abort) or E (error)
as an argument. The argument is a ReturnParameters object that is used to store
the content of the different Bapi Return structures generically.
It is thus possible to retrieve the content of each field of the error message allowing for the development of an appropriate exception handler.
catch (BapiException e)n e)
Console.WriteLine("BAPI Exception caught");
Console.WriteLine("NUMBER: " + e.BapiReturn.Number);
Console.WriteLine("Message: " + e.BapiReturn.Message);
It is recommended to have at least two catch blocks.
The first catch statement is then used for the SAP specific exceptions of type BapiException
while the second is used for others (generic) exceptions,
for example errors from the runtime or other resources.
The class ReturnParameters is used to store
generically the content of the complex structures BAPIRET2, BAPIRET1, BAPIRETURN
and BAPIRETURN1. It therefore has properties for each field that can be
returned by on of the four structures. The property ReturnTable is used
by +BapiRet +objects to hold a list of objects based on ReturnParameters.
|ID||string||Message, message class||X||X||X|
|CODE||string||Message, message code||X|
|NUMBER||string||Message, message number||X||X||X|
|LOG_NO||string||Application log: Log number||X||X||X||X|
|LOG_MSG_NO||string||Application log: Message number running internally within log||X||X||X||X|
|MESSAGE_V1||string||Message, message variables
Up to four variable values
Variables are used in the same order as the
appear in the message text
|PARAMETER||string||Name of parameter in which the error message occurred||X|
|ROW||int||Row in parameter in which the error message occurred||X|
|FIELD||string||Field in parameter in which the error message occurred||X|
|SYSTEM||string||System (logical system) from which the message originates||X|
Table: Structure of ReturnParameters.</p>