Epicor Rest Helper (Nuget) Updated V2

Pull Request

Is the way that you make enhancements to Github repositories.

1 Like

this part I knew, but the acronym I did not! Thank you :pray:

1 Like

HI JosĆØ,
I have a timeout problem using EpicorRest.BaqGet, but i never found timeout setting in api setting. I use the rest api 2.0.4.

Please can send me how I can set Timeout?

Thanks
Massimo

Your timeout is in your baq? We donā€™t control timeout at the REST level.

1 Like

Thank You Jose,
I try to run BAQ from Epicor Api Help and data was returned without timeout error,
I try in a visual studuio project with Epicor rest Api Nuget and i receive timeout, but I can see on sql server query running.
i Think this error is relatet to ExecutionTimeout of a HTTPrequest.
is there the possibility to set it?
thanks
Massimo

How long is the query taking?

This query take +/- 180 sec. Timeout error is returned after 120 sec.

Published Update 2.1.0.1 of the Nuget with all the improvements below thanks to @A9G-Data-Droid :clap:

Moved Main Library to .NEt 4.8, Moved "Core" to .Net 5
Convert packages.config to PackageReference
Use new NetAnalyzers to close warnings
Run Code Cleanup Profile 2
Make compatible with new version of RestSharp
Add async to all V2 methods
Normal methods share code with async versions
Add accept header to fix issue with getting JSON schema when expecting XML

We will update the documentation with some examples of the Async calls as soon as we get a chance. But the new methods work exactly the same as the old ones (except async) and we kept the old method there so you arenā€™t required to use the async version for backwards compatibility.

Thanks again to @A9G-Data-Droid for all the hard work, Iā€™m sure everyone appreciates it!

6 Likes

WARNING

This new version hasnā€™t been through much testing. Please do your own unit testing before using this in a production app. Let me know if there are any problems introduced by this new version.

Why New Async Methods?

If youā€™re not familiar with the .NET Async\Await pattern I recommend reading anything written by Stephen Cleary who is an MS MVP and expert on the topic.

The TL;DR is that these tools simplify multi-threaded code by abstracting out the hard parts. The main use here is to avoid deadlocking your GUI thread.

If you were to run an HTTP request, like the ones found in this library, on your GUI thread then the GUI would become unresponsive while waiting for network response. This is a bad user experience and can lead to the aforementioned deadlock where the GUI never comes back!

How do I use the new methods?

To solve this problem you want to use async\await pattern all the way up and down the call chain. This requires changing the signatures of every method from the GUI up to the actual HTTP request and back.

Letā€™s say you want to select a BAQ from a ListBox called AvailableBaqIds and display the results of that BAQ in DataTable. You need to make the event handler async so that the GUI can await long running actions and then update the GUI upon return, with the results.

Your old code might look like this:

private void AvailableBaqIds_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (AvailableBaqIds.SelectedIndex >= 0)
    {
        var baqID = e.AddedItems[0]?.ToString() ?? string.Empty;
        _baqViewModel.SetBaqDataTableModel(baqID);
    }
}

internal void SetBaqDataTableModel(string baqId)
{
      BaqDataTable = EpicorRest.BaqGetDataTable(baqId);
}

Now to make these methods async we are going to add the keyword async to the method signature and then when we make a call to another async method we are going to await the return. The methods become a Task so you canā€™t use them without awaiting.

Look at the updated code and check for the keywords: async, Task, and await:

private async void AvailableBaqIds_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (AvailableBaqIds.SelectedIndex >= 0)
    {
        var baqID = e.AddedItems[0]?.ToString() ?? string.Empty;
        await _baqViewModel.SetBaqDataTableModelAsync(baqID);
    }
}

internal async Task SetBaqDataTableModelAsync(string baqId)
{
      BaqDataTable = await EpicorRest.BaqGetDataTableAsync(baqId);
}

These are all void methods. If you want to return a value from a function the signature is a bit strange. You have to make it a task of the type you want to return so that string would become Task<string>.

So, for example, the function that returns the datatable changes from this:

public static DataTable BaqGetDataTable

To this:

public static async Task<DataTable> BaqGetDataTableAsync

Iā€™ve added Async to the end of the name of each async method. This isnā€™t required but itā€™s only to show that there are two identical methods, one of which will run asynchronously. This is a common pattern used by Microsoft so Iā€™ve copied their style here.

3 Likes

I am trying to make simple program to run a baq but when it gets to running EpicorRest.BaqGetDataTable(baqID); the program simply hangs and I do not get any errors. The baq I am testing runs in under a second otherwise. Would anyone be able to point me in a direction to fix it? I am on version 10.2.300.

 EpicorRest.APIVersion = EpicorRestVersion.V1;
 EpicorRest.AppPoolHost = "server";
 EpicorRest.AppPoolInstance = "instance";
 EpicorRest.UserName = "user";
 EpicorRest.Password = "pass";
 string baqID = "mybaq";
 DataTable dt = EpicorRest.BaqGetDataTable(baqID);
 dataGridView1.DataSource = dt;

Just migrated to Kinetic 2022.1.8 over the weekend and had to ā€˜fixā€™ a program. I also tried the BaqGetDataTable using the latest REST helper and got nothing

I went back to EpicorRestV1 and got it working for now. I would enjoy seeing the answer to your post

I am looking at it looks like a bug. Stand by

Okay I have pushed a fix with Update 2.1.0.2 we forgot to provide an API key to V2 of the get BAQ meta data. #Fixed

2 Likes

Thank you for the quick action however I am still encountering the same issue after updating.

I think what is confusing is that youā€™ve set your APIVersion = EpicorRestVersion.V1; and then you are calling a V2 method. I have never used the V1 API methods but it looks like the GetBAQResults method is the V1 version.

This library could be clearer about how this works by separating V1 and V2 objects. You shouldnā€™t be allowed to call a V2 method when you want a V1. The code would have to be restructured a bit to make this true. I would force the developer to new either a V1 or V2 object so they only see the methods available for their use case.

1 Like

So I made a test to set my APIVersion = EpicorRestVersion.V1 and then I called the V2 method BaqGetDataTable just like you show that you do. My test completed successfully. Iā€™m not entirely sure how this is supposed to work but I can tell that the functions in the V2 code are designed to build a BAQ endpoint based on the APIVersion. What this says to me is that the V2 code paths might work against API V1. Maybe I donā€™t understand what Iā€™m looking at. Jose will have to clarify. Maybe the V1 methods are version one of this library and not pertaining to the API version.

All that said, the issue of hanging you are describing sounds like the GUI deadlock I was describing. Please switch to using Async methods and see if that fixes the problem.

1 Like

So V1 is supposed to be compatible with V1 of the EpicorAPI

V1 of this Library is instantiated by using EpicorRestV1 object (so they are separate)

If you select V1 you just get a separate end point but for this particular purpose either one yields the same result.

Thanks for the confirmation.

So if Robert wants to use the V1 API he should be switching his EpicorRest setup for EpicorRestV1?

Current version of EpicorRest is what he should use, with either V1 or V2 of the Epicor API.

Iā€™m testing this method and It works for me in one project and not in anotherā€¦ #confusedā€¦ digging further

1 Like

If your program used to be for .NET 4.7.X you may need to upgrade the System.Text.JSON nuget to the latest version that was the issue for me, works fine now.

Is this a console app?

2 Likes