huysentruitw / SapNwRfc

SAP NetWeaver RFC library for .NET 5, .NET Core and .NET Framework
MIT License
149 stars 45 forks source link

Expression must be writeable (Parameter 'left') #102

Closed GustavoDamasceno closed 3 months ago

GustavoDamasceno commented 3 months ago

I am making a request to an RFC called ZRFC_EASY_PALLET_04, and since it does not take any parameters, I make a request to it and it returns a structure called E_ZSDS_EASYP_JSON.

I collect the information from the field JS_STRING that is inside this structure. Essentially, the structure is as follows: {STRUCTURE ZSDS_EASYP_JSON { FIELD JS_STRING= }}

So, I created this code to get the return in the variable result:

SapConfig sapConfig = new SapConfig();

string connectionString = sapConfig.SapconnectionString(ConfigurationManager.AppSettings["Ambiente"].ToString());
using var connection = new SapConnection(connectionString);

try
{
    connection.Connect();

    Console.WriteLine("Carregando dados do SAP...");

    using var someFunction = connection.CreateFunction("ZRFC_EASY_PALLET_04");
    var result = someFunction.Invoke<SapFunctionResult>();

    Console.WriteLine(result.E_ZSDS_EASYP_JSON);

}
catch (Exception ex)
{

    throw ex;
}

And I created my SapFunctionResult class like this:

public class SapFunctionResult
{
    [SapName("E_ZSDS_EASYP_JSON")]
    public List<E_ZSDS_EASYP_JSON> E_ZSDS_EASYP_JSON { get; set; }
}

public class E_ZSDS_EASYP_JSON
{
    [SapName("JS_STRING")]
    public string JS_STRING { get; set; }
}

However, when the code executes the invoke, the following error appears: Expression must be writeable (Parameter 'left')

Has anyone experienced this before? Could you please help me?

tom-j-irvine commented 3 months ago

I think I see your issue - refer to this documentation for additional information: https://github.com/huysentruitw/SapNwRfc?tab=readme-ov-file#define-models-with-a-nested-table

if E_ZSDS_EASYP_JSON is a flat structure with a field named JS_STRING, you would declare E_ZSDS_EASYP_JSON like this:

[SapName("E_ZSDS_EASYP_JSON")]
public E_ZSDS_EASYP_JSON E_ZSDS_EASYP_JSON { get; set; }

if it is a table (so, multiple rows of E_ZSDS_EASYP_JSON), it should be declared as an array, not a List

[SapName("E_ZSDS_EASYP_JSON")]
public E_ZSDS_EASYP_JSON[] E_ZSDS_EASYP_JSON { get; set; }

I would also suggest using more C# standard names - the SapName attribute lets you map the ABAP name to something more appropriate in c#. An example below (though, I have no idea if those names are actually appropriate):

public class EasyPResult
{
    [SapName("E_ZSDS_EASYP_JSON")]
    public EasyPJson[] JsonItems { get; set; }
}

public class EasyPJson
{
    [SapName("JS_STRING")]
    public string JsonString { get; set; }
}
GustavoDamasceno commented 3 months ago

Dude, thanks again! Before using a list, I was using an array as I saw in the documentation, but it was returning an RFC_CONVERSION_FAILURE error. However, by doing it the way you indicated below, it worked.

public class SapFunctionResult
{
    [SapName("E_ZSDS_EASYP_JSON")]
    public E_ZSDS_EASYP_JSON E_ZSDS_EASYP_JSON { get; set; }
}

I’ll follow your advice on the names... Thanks again! I owe you one - when you come to Brazil, I’ll treat you to lunch, hahaha.

GustavoDamasceno commented 3 months ago

Close

tom-j-irvine commented 3 months ago

If that works, the E_ZSDS_EASYP_JSON parameter must be a flat structure - so, a single value, but possibly with multiple fields. You would declare it as an array if it was table-type where there could be multiple rows of values returned.

Have not been to Brazil, but it looks beautiful. A long trip for lunch though.