cancel
Showing results for 
Search instead for 
Did you mean: 

Best practice how to deal with action parameters in RAP service

maartenweijer
Explorer

Hi all,

In the past we used to develop quiet a lot of Z-programs. Our goal is that we replace Z-programs by RAP services and make them compliant with the ABAP Cloud development rules. This needs to be done on a S/4 HANA On Premise system. Current version is 2020, in a few months it should be 2023.

One of the questions that was raised was how to deal with parameters where we can have pretty much the same functionality as with select options in a Z-program, so including, excluding, between etc options for the values entered. I am aware that it might not be possible to achieve to exact same thing, but what would be the best approach to handle pretty much what we want?

An example is the below action:

  static action execute parameter ZSC_IO_ODS_TO_FNR_PARAM_INB  result [1] ZSC_WMS_STOCK_ABSTRACT_OUT;

Parameter ZSC_IO_ODS_TO_FNR_PARAM_INB   looks like this:

@EndUserText.label: 'Inbound parameters'
define abstract entity ZSC_IO_ODS_TO_FNR_PARAM_INB
{
    changes_x_days_back : abap.char( 1000 );
    supplier            : abap.char( 1000 );
    supplying_plant     : abap.char( 1000 );
    plant               : abap.char( 1000 );
    product            : abap.char( 1000 );
}

From Postman we would be able to call it like this:

*/sap/opu/odata/sap/ZSC_IO_ODS_TO_FNR_SB/execute?changes_x_days_back='5'&supplier=''& supplying_plant=''&plant='1003'&product=''

With the above structure we could easily pass multiple values of a field separating it by a semicolon.

In the action we would be able to take over the value of ‘plant’ like this (where the part how to deal with the semicolon and split into separate values would still need to be programmed). An application job is then started later. But what if we want that all stores are selected between 1003 - 1099, but not 1050 as an example? Then it becomes a bit more complex.

   LOOP AT keys ASSIGNING FIELD-SYMBOL(<lwa_keyfields>).

      IF <lwa_keyfields>-%param-plant IS NOT INITIAL.

        CLEAR: lwa_job_parameters,

               lwa_job_parameters_value,

               lta_job_parameters_value[].

        lwa_job_parameters-name = 'plant'.

        lwa_job_parameters_value-sign = 'I'.

        lwa_job_parameters_value-option = 'EQ'.

        lwa_job_parameters_value-low = <lwa_keyfields>-%param-plant.

        APPEND lwa_job_parameters_value TO lta_job_parameters_value.

        lwa_job_parameters-t_value = lta_job_parameters_value.

        APPEND lwa_job_parameters TO lta_job_parameters.

      ENDIF.

   ENDLOOP.

Is there a best practice how we can achieve what we want with the parameters where we have a lot of flexibility? 

Kind regards,

Maarten Weijer

 

 

 

 

Accepted Solutions (0)

Answers (1)

Answers (1)

RalfHandl
Product and Topic Expert
Product and Topic Expert
0 Kudos

OData best practice for filtering results is using the $filter query option and express your desired result as a filter condition on the result structure. Assuming you result is basically an array of objects with a field Plant, you would pass

$filter=Plant eq '1003' or Plant eq '1004'

Worst practice is tunneling your own "query language" through a string parameter: you are in full control of what you do within the single-quoted string value and how to interpret the string as a "command" to do whatever you want - wipe the database, inject some code snippet, or treat it as an ABAP select-option to filter your result. This also means that you have full responsibility for validating and securely interpreting the content of your "command string".

maartenweijer
Explorer
0 Kudos

This could work , but is there an easy way to convert this string to a ranges table? I debugged the behavior implementation class, but if I would pass a value like this for 'Plant', it is seen as a string, which is expected of course.

Example:

*/sap/opu/odata/sap/ZSC_IO_ODS_TO_FNR_SB/execute?changes_x_days_back='5'&supplier=''& supplying_plant=''&plant='Plant eq '1003' or Plant eq '1004''&product=''&sap-client=400

RalfHandl
Product and Topic Expert
Product and Topic Expert
0 Kudos

My idea was to use $filter instead of the action parameters, so the action call would become

*/sap/opu/odata/sap/ZSC_IO_ODS_TO_FNR_SB/execute?changes_x_days_back='5'&$filter=Plant eq '1003' or Plant eq '1004'&sap-client=400

Not sure how to achieve this with RAP, back in the days of manual OData service implementation the DPC method would receive a parameter io_request or io_tech_request_context that would allow accessing the filter value and have it converted into a deep structure with nested ranges tables.

maartenweijer
Explorer
0 Kudos

I tried it by adding this to the URL, but I get back the message "System query options '$expand,$filter,$orderby,$skip,$top,$skiptoken,$inlinecount,$select' are not allowed in the requested URI". It looks like the action is only accepting parameters that we defined and that is also what I experienced. I looked again at the data we have available while debugging, but io_request and io_tech_request_context are both not available (see below image). If we would have had them, I know I would be able to convert it easily.

 

maartenweijer_0-1714658834531.png