# Interfacing with API in C# console program

**URL:** <https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059>\
**Category:** Kinetic ERP\
**Tags:** kinetic, customization, rest\
**Created:** [July 14, 2023, 6:56pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059 "2023-07-14T18:56:14Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 6:56pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/1 "2023-07-14T18:56:14Z")

</div>

I have been tasked with interfacing with a third-party software to manage invoice submittal and payment. It’s all done via ftp and I have the server setup to handle the ftp requests outside of Epicor.

I created the query within the Epicor space with the thought to have the Epicor server perform the query and return the results to me via REST. This is working fantastically but I’m struggling to turn this into JSON. Each time the call returns a blob string which I’ve tried a few different avenues to ‘prettify’ it.

 ![image](https://www.epiusers.help/uploads/default/original/3X/b/5/b59201ae34c336b683bf68a86cb335ee7aa491e6.png)

**Code below** :  
Main

```auto
HttpClient client = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://centralusdtadtl15.epicorsaas.com/saas5102third/api/v2/odata/100000/BaqSvc/rMasterVendor/Data");
            StringContent content = new StringContent("", null, "text/plain");
            

            // Build API Request with Headers
            request.Headers.Add("x-api-key", "API Key here");
            request.Headers.Add("Authorization", "Basic <auth string>");
            request.Content = content;

            HttpResponseMessage response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();

            var BAQResults = await response.Content.ReadAsStringAsync();
            EpiJSON json = new EpiJSON();
            JsonConvert.PopulateObject(BAQResults, json);

            Console.WriteLine(BAQResults);

```

EpiJSON

```auto
[JsonObject]
    public class EpiJSON
    {
        public string? context { get; set; }
        public List<EpiVendor>? value { get; set; }
    }

```

EpiVendor

```auto
public class EpiVendor
    {
        #region Fields

        private string? Calculated_CompanyID { get; set; }
        private string? Vendor_VendorID { get; set; }
        private string? Calculated_VendorCode { get; set; }
        private string? Calculated_VendorLocationID { get; set; }
        private string? Calculated_VendorLocationCode { get; set; }
        private string? Vendor_Name { get; set; }
        private string? Vendor_Address1 { get; set; }
        private string? Vendor_Address2 { get; set; }
        private string? Vendor_Address3 { get; set; }
        private string? Vendor_City { get; set; }
        private string? Vendor_State { get; set; }
        private string? Vendor_Zip { get; set; }
        private string? Vendor_Country { get; set; }
        private int? PurTerms_NumberOfDays { get; set; }
        private string? EntityGLC_GLControlCode { get; set; }
        private string? Calculated_ERSFlag { get; set; }
        private string? Calculated_PaySiteFlag { get; set; }
        private string? Calculated_PurchasingSiteFlag { get; set; }
        private string? Vendor_CurrencyCode { get; set; }
        private string? Calculated_PaymentCurrency { get; set; }
        private string? PayMethod_Name { get; set; }
        private string? Calculated_EMailAddress { get; set; } // Vendor Portal Contact Email Address
        private string? Calculated_Field2 { get; set; }
        private string? Calculated_Field3 { get; set; }
        private string? Calculated_Field4 { get; set; }
        private string? Calculated_Field5 { get; set; }
        private bool Calulated_Status { get; set; }

        #endregion

```

It kept throwing errors about non-nullable properties if I don’t use the null-conditional operator. Could somebody explain that too possibly?

My thought is to call the API, iterate through the dataset and I have to create a pipe-delimited text file from a few different tables, once every 2 hours and upload to the ftp server. I have the ftp script written and uploading files correctly, it’s just getting this data into a format that I know what to do with.

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 7:23pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/2 "2023-07-14T19:23:20Z")

</div>

Might take me a second to parse what you are doing exactly, but if you want to “prettify” the json you are getting back you can just use Newtonsoft.Json, and do this:

```cs
//ref Newtonsoft.Json
using Newtonsoft.Json;

string pretty = JToken.Parse(BAQResults).ToString();

```

---

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 7:28pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/3 "2023-07-14T19:28:07Z")

</div>

Thanks for your response!

I just attempted that and got it to prettify but it cuts out over half of my dataset for some reason. I’m pulling two companies worth of data. The results that I get when it IS formatted correctly cuts out all Vendors of one company and picks of in the letter ‘N’ in the second company. Its super weird because it’s not even the start of that Vendor, it’s half of the object too. It’s like a character is in the string that’s throwing it off somehow but there isn’t anything crazy in the raw data and Postman display the results with no problem.

![image](https://www.epiusers.help/uploads/default/original/3X/f/1/f18fee70ceda595d613075ce5dc9504c762a3cf6.png)

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 7:29pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/4 "2023-07-14T19:29:56Z")

</div>

Interesting. You can leave off the `Formatting.Indented`, JToken.Parse().ToString() default is indented.

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 7:31pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/5 "2023-07-14T19:31:02Z")

</div>

Why do you need it pretty?

If you need to see what’s going on, just prettify one row.

---

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 7:32pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/6 "2023-07-14T19:32:47Z")

</div>

I come from a JavaScript background and my mind thought about turning it into JSON and iterating through the dataset that way. Am I thinking about it wrong? Would it be better to keep it as a string? How do I iterate through that?

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 7:33pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/7 "2023-07-14T19:33:13Z")

</div>

It _ **IS** _ Json.

---

<div class="post-metadata">

**Author:** ![josecgomez](https://www.epiusers.help/user_avatar/www.epiusers.help/josecgomez/32/55731_2.png) [@josecgomez](https://www.epiusers.help/u/josecgomez)\
**Post date:** [July 14, 2023, 7:40pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/8 "2023-07-14T19:40:53Z")

</div>

I would recommed using a library if you don’t want to deal with all the parsing and stuff yourlself

> [@Epicor Rest Helper (Nuget) Updated V2](https://www.epiusers.help/t/epicor-rest-helper-nuget-updated-v2/76250):
>
> @jgiese.wci and I with contributions from @A9G-Data-Droid Updates Version 2.2.0.1 Fixes sync freesing issues Thanks @A9G-Data-DroidAdded multi mapper object| Added GetEnvironment| Replaced Dictionary\<string,string\> with MultiMap\<string,string\> this allows duplicate “keys” which is necessary for some epicor calls. Added GetEnvironment() and GetEnvironmentAsync() calls using EpicorRestSharedClasses; MultiMap\<string, string\> parms = new MultiMap\<string, string\>(); parms.Add("CompanyList", "C…

This nuget returns an object which contains the response as both a JSON string and a Dynamic C# object

---

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 7:48pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/9 "2023-07-14T19:48:12Z")

</div>

Got it. That’s what was confusing me along with I believe I hit a buffer limit on the console. I put an incrementor on a loop while it printed and saw that even though it was half of an object, the count started at row 5,xxx. I created it as a file and saw it.

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 7:53pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/10 "2023-07-14T19:53:15Z")

</div>

So you good now?

---

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 8:07pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/11 "2023-07-14T20:07:31Z")

</div>

I’ll figure the rest out hopefully this weekend

---

<div class="post-metadata">

**Author:** ![utaylor](https://www.epiusers.help/user_avatar/www.epiusers.help/utaylor/32/64664_2.png) [@utaylor](https://www.epiusers.help/u/utaylor)\
**Post date:** [July 14, 2023, 8:45pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/12 "2023-07-14T20:45:58Z")

</div>

I love it when people say the whole term: JavaScript Object Notation

---

<div class="post-metadata">

**Author:** ![dakhit](https://www.epiusers.help/letter_avatar_proxy/v4/letter/d/7bcc69/32.png) [@dakhit](https://www.epiusers.help/u/dakhit)\
**Post date:** [July 14, 2023, 10:32pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/13 "2023-07-14T22:32:27Z")

</div>

I know @josecgomez recommended an easier way which i’ll totally take up if I just can’t get this but I’m kind of determine to understand this and finish it this way 😅

I jumped back into this after getting home. I’m getting stuck at the `@odata.context` portion of the JSON string. How do I map this via deserialization? That’s not a valid variable name. Would creating a class of oData and adding a field for context that holds a string value then make the oData variable of the oData class?

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 10:36pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/14 "2023-07-14T22:36:00Z")

</div>

I gotta run, but I would just get rid of it.

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 14, 2023, 11:47pm UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/15 "2023-07-14T23:47:08Z")

</div>

Just ignore it.

```cs
namespace Discard1;

using System.IO;
using Newtonsoft.Json;

public class EpiJSON
{
    public List<ABCCode> value;
}
public class ABCCode
{
    public string? ABCCode_Company;
    public string? ABCCode_ABCCode;
    public int? ABCCode_CountFreq;
    public bool? ABCCode_ExcludeFromCC;
    public string? ABCCode_StockValPcnt;
    public string? ABCCode_PcntTolerance;
    public bool? ABCCode_CalcPcnt;
    public bool? ABCCode_CalcQty;
    public bool? ABCCode_CalcValue;
    public string? ABCCode_QtyTolerance;
    public string? ABCCode_ValueTolerance;
    public int? ABCCode_ShipToCustNum;
    public Guid? ABCCode_SysRowID;
    public Guid? RowIdent;        
}

class Program
{
    static void Main(string[] args)
    {
        string json = File.ReadAllText("abc.json");

        var anObject = JsonConvert.DeserializeObject<EpiJSON>(json);

        foreach(var abc in anObject.value)
        {
           Console.WriteLine(abc.ABCCode_SysRowID.ToString());
        }
    }
}

```

Input:

```js
{
  "odata.metadata": "https://aserverliveshere.nope/server/api/v1/BaqSvc/KEV_ABC/$metadata#Epicor.DynamicQuery.QueryResults",
    "value": [
      {
        "ABCCode_Company": "1234567",
        "ABCCode_ABCCode": "A",
        "ABCCode_CountFreq": 3,
        "ABCCode_ExcludeFromCC": false,
        "ABCCode_StockValPcnt": "0",
        "ABCCode_PcntTolerance": "0.00",
        "ABCCode_CalcPcnt": false,
        "ABCCode_CalcQty": false,
        "ABCCode_CalcValue": false,
        "ABCCode_QtyTolerance": "0",
        "ABCCode_ValueTolerance": "0",
        "ABCCode_ShipToCustNum": 0,
        "ABCCode_SysRowID": "8429abd7-2649-4201-ac11-e2df2a9cd71a",
        "RowIdent": "00000001-0000-0000-0000-000000000000"
      },
      {
        "ABCCode_Company": "1234567",
        "ABCCode_ABCCode": "B",
        "ABCCode_CountFreq": 7,
        "ABCCode_ExcludeFromCC": false,
        "ABCCode_StockValPcnt": "0",
        "ABCCode_PcntTolerance": "0.00",
        "ABCCode_CalcPcnt": false,
        "ABCCode_CalcQty": false,
        "ABCCode_CalcValue": false,
        "ABCCode_QtyTolerance": "0",
        "ABCCode_ValueTolerance": "0",
        "ABCCode_ShipToCustNum": 0,
        "ABCCode_SysRowID": "d1840ac1-789e-406a-af2f-9bbbc1e77f70",
        "RowIdent": "00000002-0000-0000-0000-000000000000"
      } ]
  }

```

Output:

```plaintext
8429abd7-2649-4201-ac11-e2df2a9cd71a
d1840ac1-789e-406a-af2f-9bbbc1e77f70

```

---

<div class="post-metadata">

**Author:** ![klincecum](https://www.epiusers.help/user_avatar/www.epiusers.help/klincecum/32/100137_2.png) [@klincecum](https://www.epiusers.help/u/klincecum)\
**Post date:** [July 15, 2023, 12:08am UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/16 "2023-07-15T00:08:21Z")

</div>

The full code for ignore is:

```cs
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

var anObject = JsonConvert.DeserializeObject<EpiJSON>(json, jsonSerializerSettings);

```

The default is `Ignore`, so it works without it. [JsonSerializerSettings.MissingMemberHandling Property](https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonSerializerSettings_MissingMemberHandling.htm#:~:text=Gets%20or%20sets%20how%20missing,The%20default%20value%20is%20Ignore.)

> Gets or sets how missing members (e.g. JSON contains a property that isn’t a member on the object) are handled during deserialization. The default value is [Ignore](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_MissingMemberHandling.htm).

You can also use `Error`, and catch it.

---

<div class="post-metadata">

**Author:** ![HLalumiere](https://www.epiusers.help/letter_avatar_proxy/v4/letter/h/bc8723/32.png) [@HLalumiere](https://www.epiusers.help/u/HLalumiere)\
**Post date:** [July 15, 2023, 7:01am UTC](https://www.epiusers.help/t/interfacing-with-api-in-c-console-program/105059/17 "2023-07-15T07:01:56Z")

</div>

You don’t need to define contracts to use deserialized objects, just use `dynamic` late binding… This is how I run BAQs from C#. Don’t use the oData (just V2 custom methods) because sometimes I need to pass parameter to BAQs that would make the url too long.

```auto
var baseAddress = $"{Session.AppServerURL}api/v2/odata/{Session.CompanyID}";

try
{
    using (var client = new HttpClient())
    {
        // Get the UBAQ parameters dataset
        var queryIdParamJson = JsonConvert.SerializeObject(new { queryID = baqId });

        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Post,
            RequestUri = new Uri(baseAddress + "/Ice.BO.DynamicQuerySvc/GetQueryExecutionParametersByID"),
            Headers = 
            {
                { "Authorization", "Basic " + auth },
                { "Accept", "application/json" },
                { "X-API-Key", apiKey },
            },
            Content = new StringContent(queryIdParamJson, Encoding.UTF8, "application/json")
        };

        var result = client.SendAsync(request).Result;

        if (result.IsSuccessStatusCode)
        {
            dynamic jsonRsp = JsonConvert.DeserializeObject(result.Content.ReadAsStringAsync().Result);

            var ds = jsonRsp.returnObj;

            // Set UBAQ parameters
            foreach (var param in ds.ExecutionParameter)
            {
                if (param.ParameterID == "param1")
                {
                    param.ParameterValue = param1Value;
                    param.IsEmpty = false;
                }
                else if (param.ParameterID == "param2")
                {
                    param.ParameterValue = param2Value;
                    param.IsEmpty = false;
                }
            }

            var queryParamsJson = JsonConvert.SerializeObject(new { queryID = baqId, executionParams = ds });

            request = new HttpRequestMessage
            {
                Method = HttpMethod.Post,
                RequestUri = new Uri(baseAddress + "/Ice.BO.DynamicQuerySvc/ExecuteByID"),
                Headers =
                {
                    { "Authorization", "Basic " + auth },
                    { "Accept", "application/json" },
                    { "X-API-Key", apiKey },
                },
                Content = new StringContent(queryParamsJson, Encoding.UTF8, "application/json")
            };

            // Call UBAQ
            result = client.SendAsync(request).Result;

            if (result.IsSuccessStatusCode)
            {
                jsonRsp = JsonConvert.DeserializeObject(result.Content.ReadAsStringAsync().Result);

                // Get the returned dataset as a dynamic
                ds = jsonRsp.returnObj;

                foreach (var row in ds.Results)
                {
                    // Do something
                    var a = (decimal)row.Calculated_SomeCalcField;
                }
            }
        }
    }
}
catch (Exception ex)
{
    // Handle exceptions
}

```

If you need to map the results to an internal type for your application, just do it in the final foreach.
