You can use .NET Open Client DATASET-HANDLE and TABLE-HANDLE parameters to send/receive datasets and temp-tables to/from the application server, as shown in the following example code.

ABL code

dynOutDataSet.p
DEFINE INPUT PARAMETER minCredit AS INTEGER.
DEFINE INPUT PARAMETER maxCredit AS INTEGER.

DEFINE OUTPUT PARAMETER DATASET-HANDLE dsetHandle.
dynInpOutDataSet.p
DEFINE INPUT PARAMETER moreCredit AS INTEGER.

DEFINE INPUT-OUTPUT PARAMETER DATASET-HANDLE dsetHandle.

DEFINE TEMP-TABLE ttCust 
        FIELD CustNum LIKE Customer.Custnum 
        FIELD NAME LIKE Customer.NAME 
        FIELD Address LIKE Customer.Address 
        FIELD City LIKE Customer.City 
        FIELD CreditLimit LIKE Customer.CreditLimit .

DEFINE DATASET myDS FOR ttCust.
dynInpDataSet.p
DEFINE INPUT PARAMETER DATASET-HANDLE dsetHandle.
dynOutTable.p
DEFINE INPUT PARAMETER minCredit AS INTEGER.
DEFINE INPUT PARAMETER maxCredit AS INTEGER.
DEFINE OUTPUT PARAMETER TABLE-HANDLE ttHandle.

DEFINE TEMP-TABLE ttCust 
        FIELD CustNum LIKE Customer.Custnum 
        FIELD NAME LIKE Customer.NAME 
        FIELD Address LIKE Customer.Address 
        FIELD City LIKE Customer.City 
        FIELD CreditLimit LIKE Customer.CreditLimit .
      
DEFINE DATASET myDS FOR ttCust.
dynInpOutTable.p
DEFINE INPUT PARAMETER moreCredit AS INTEGER.
DEFINE INPUT-OUTPUT PARAMETER TABLE-HANDLE ttHandle.
dynInpTable.p
DEFINE INPUT PARAMETER TABLE-HANDLE ttHandle.

OpenAPI code

using Progress.Open4GL;
using Progress.Open4GL.Proxy;
using System.Data;

//Example code using DataSet-Handle and TempTable-Handle parameters on .NET client

DataSet myDSet;

try
{
    // Connect to the AppServer
    Connection myConn = new Connection("http://<host>/apsv", "", "", "");

    OpenAppObject openAO = new OpenAppObject(myConn, "");

    // Set Session model for state-free
    myConn.SessionModel = 1;

    System.Int32 minCreditLimit = 1500;
    System.Int32 maxCreditLimit = 2000;
    System.Int32 moreCredit = 3000;

    DataTable myDT;

    //////////////////////////////////////////////////////////////
    /// Example code passing DataSet-Handle as output parameter


    // Create the ParamArray
    ParamArray parms = new ParamArray(3);

    // Set up input parameters
    parms.AddInteger(0, minCreditLimit, ParamArrayMode.INPUT);
    parms.AddInteger(1, maxCreditLimit, ParamArrayMode.INPUT);

    // Set up Out parameters
    // Okay to not specify metadata
    parms.AddDatasetHandle(2, null, ParamArrayMode.OUTPUT, null);

    // Run the procedure
    System.Console.Out.WriteLine("Calling dynOutDataSet.p");
    openAO.RunProc("dynOutDataSet.p", parms);

    // Retrieve data and print
    myDSet = (DataSet)parms.GetOutputParameter(2);
    System.Console.Out.WriteLine("DataTable " + myDT.TableName + " contains " + myDT.Rows.Count + " rows.");

    /////////////////////////////////////////////////////////////////
    /// Example code passing DataSet-Handle as input-output parameter


    parms = new ParamArray(2);

    // Set up input parameters
    parms.AddInteger(0, moreCredit, ParamArrayMode.INPUT);

    // Set up Inp-Out parameters
    ProDataSetMetaData dsetMetaData = createDSetMetaData();
    parms.AddDatasetHandle(1, myDSet, ParamArrayMode.INPUT_OUTPUT, dsetMetaData);

    System.Console.Out.WriteLine("Calling dynInpOutDataSet.p");
    openAO.RunProc("dynInpOutDataSet.p", parms);

    // Retrieve data and print
    myDSet = (DataSet)parms.GetOutputParameter(1);
    System.Console.Out.WriteLine("DataTable " + myDT.TableName + " contains " + myDT.Rows.Count + " rows.");

    /////////////////////////////////////////////////////////////////
    /// Example code passing DataSet-Handle as input parameter


    parms = new ParamArray(1);

    parms.AddDatasetHandle(0, myDSet, ParamArrayMode.INPUT, dsetMetaData);

    System.Console.Out.WriteLine("Calling dynInpDataSet.p");
    openAO.RunProc("dynInpDataSet.p", parms);

    //////////////////////////////////////////////////////////////
    /// Example code passing Table-Handle as output parameter


    System.Console.Out.WriteLine("\n\nTempTable Examples");

    // Create the ParamArray
    parms = new ParamArray(3);

    // Set up input parameters
    parms.AddInteger(0, minCreditLimit, ParamArrayMode.INPUT);
    parms.AddInteger(1, maxCreditLimit, ParamArrayMode.INPUT);

    // Set up Out parameters
    // Okay to not specify metadata
    parms.AddTableHandle(2, null, ParamArrayMode.OUTPUT, null);

    // Run the procedure
    System.Console.Out.WriteLine("Calling dynOutTable.p");
    openAO.RunProc("dynOutTable.p", parms);

    // Retrieve data and print
    myDT = (DataTable)parms.GetOutputParameter(2);
    System.Console.Out.WriteLine("DataTable " + myDT.TableName + " contains " + myDT.Rows.Count + " rows.");


    /////////////////////////////////////////////////////////////////
    /// Example code passing Table-Handle as input-output parameter


    parms = new ParamArray(2);

    // Set up input parameters
    parms.AddInteger(0, moreCredit, ParamArrayMode.INPUT);

    // Set up Out parameters
    TempTableMetaData tableMetaData = createTableMetaData();
    parms.AddTableHandle(1, myDSet.Tables[0], ParamArrayMode.INPUT_OUTPUT, tableMetaData);

    System.Console.Out.WriteLine("Calling dynInpOutTable.p");
    openAO.RunProc("dynInpOutTable.p", parms);

    // Retrieve data and print
    myDT = (DataTable)parms.GetOutputParameter(1);
    System.Console.Out.WriteLine("DataTable " + myDT.TableName + " contains " + myDT.Rows.Count + " rows.");

    /////////////////////////////////////////////////////////////////
    /// Example code passing Table-Handle as input parameter


    parms = new ParamArray(1);

    parms.AddTableHandle(0, myDSet.Tables[0], ParamArrayMode.INPUT, tableMetaData);

    System.Console.Out.WriteLine("Calling dynInpTable.p");
    openAO.RunProc("dynInpTable.p", parms);
}
catch (System.Exception e)
{
    System.Console.Out.WriteLine("Error:" + e.Message);
}




///////////////////////////////////////////////////////////////
///
ProDataSetMetaData createDSetMetaData()
{
    ProDataSetMetaData proDGMD = new ProDataSetMetaData("customerDS", "");

    TempTableMetaData custTT = createTableMetaData();

    proDGMD.AddDataTable(custTT);

    return proDGMD;
}

TempTableMetaData createTableMetaData()
{
    TempTableMetaData custTT = new TempTableMetaData("custTT", "", 5, false, 0, "", "", "");

    custTT.SetFieldMetaData(1, "CustNum", 0, Parameter.PRO_INTEGER, 0, 0);
    custTT.SetFieldMetaData(2, "Name", 0, Parameter.PRO_CHARACTER, 1, 0);
    custTT.SetFieldMetaData(3, "Address", 0, Parameter.PRO_CHARACTER, 2, 0);
    custTT.SetFieldMetaData(4, "City", 0, Parameter.PRO_CHARACTER, 3, 0);
    custTT.SetFieldMetaData(5, "CreditLimit", 0, Parameter.PRO_DECIMAL, 4, 0);

    return custTT;
}