Epicor Rest Helper (Nuget) Updated V2

@jgiese.wci and I with contributions from @A9G-Data-Droid

Updates Version 2.2.0.1

  • Fixes sync freesing issues Thanks @A9G-Data-Droid
  • Added 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", "C001");
parms.Add("CompanyList", "C002");
var result = EpicorRest.BaqGet("TestQ", parms);

//Added Get Environment
var env = EpicorRest.GetEnvironment();
// or
var env = await EpicorRest.GetEnvironmentAsync();

//Returns an Environment Object defined in EpicorRestClasses
namespace EpicorRestSharedClasses
{
    
    public class Environment
    {
        public Entity[] Companies { get; set; }
    }

    public class Entity
    {
        public string Company { get; set; }
        public string[] Plants { get; set; }
    }

}

Version 2.2.0.2 Minor Bug Fix

  • Fixes repeated event registration in CreateRequest to handle invalid certificates.

EpicorRestAPI .NET 4.8
EpicorRESTAPICore .NET 6
EpicorRESTAPIStandard .NET Standard


2.2.0.1

Version Compatible with >= .NET 4.8 and .NET Core 6+
NuGet Gallery | EpicorRestAPI 2.2.0.1 (For .NET 4.8 >)
NuGet Gallery | EpicorRESTAPICore 2.2.0.1 (For .Net >=6)
NuGet Gallery | EpicorRESTAPIStandard 2.2.0.1 (For .Net Standard)


2.1.0.3

Version Compatible with >= .NET 4.8 and .NET Core 5+
NuGet Gallery | EpicorRestAPI 2.1.0.3 (For .NET 4.8 >)
NuGet Gallery | EpicorRESTAPICore 2.1.0.3 (For .Net >=5)
NuGet Gallery | EpicorRESTAPIStandard 2.1.0.3 (For .Net Standard)


Old Version Compatible with .NET 4.5 and .NET Core 3.1
NuGet Gallery | EpicorRestAPI 2.0.4 (For .NET 4.5.1 >)
NuGet Gallery | EpicorRESTAPICore 2.0.4 (For .Net Core >=3.1)
NuGet Gallery | EpicorRESTAPIStandard 2.0.4 (For .Net Standard)

Just overhauled the Epicor Rest Nuget to support Epicor REST V2 and bring up V1 to a better standard.
We have kept the old V1 Version Available we just renamed the class to EpicorRestV1 and everything works the same as before.

However we recommend you update to the new version which supports both V1 and V2 of Epicor Rest. It supports Methods, BAQs and Functions! (AT LONG LAST!)

Initial Setup:
This will be the setup required for any use of the API, the API version defaults to V2 so you don’t need to set that unless you want to change to V1.
V1 doesn’t support Functions

EpicorRest.AppPoolHost = "subdomain.domain.tld"; //TLD to your Epicor Server
EpicorRest.AppPoolInstance = "EpicorDemo700"; //Epicor AppServer Insdtance
EpicorRest.UserName = "epicor"; //Epicor Username
EpicorRest.Password = "epicor"; //Epicor Password
EpicorRest.APIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //API key required with V2
EpicorRest.Company = "EPIC03"; //Epicor Company (Current company) Required with V2
EpicorRest.APIVersion = EpicorRestVersion.V2; //Defaults to V2
EpicorRest.License = EpicorLicenseType.Default; // You can select the type of license you want to use for the call.

Bypass Certificate Errors (Optional)

EpicorRest.IgnoreCertErrors = true; // If you are too cheap to get a free Certificate from Let's Encrypt this will bypass the errors. (Not Recommended)

Change Plant / Company, Language, and Culture (Optional)

EpicorRest.CallSettings = new CallSettings("CompanyID", "PlantID", "", ""); //This allows you to change the company and plant for a request. For V2 the company is passed in the URL via the .Company property (above) but the plant still needs to be changed either in the session, or in the callSetting.

Getting a Token:
We have always supported token authentication but we didn’t provide a way to generate a token within the API. This has now been corrected, after the initial setup above you can (if you chose to) generate a token if you want to.
Note that to generate a token you do need the username and password to be provided (as shown above)

if (EpicorRest.CreateBearerToken()) //Generates a Token and Assigns it to the API calls
{
        //Do Work Here!
}

Calling an Epicor BO:
We have made all the calls use dynamic objects this means that you don’t have to (up front) generate a class for the responses you are getting. Though you also have access to the original (serialized response if you chose to)

All calls made now generate what we are calling an EpicorResponseObject. This object contains the entire reponse send back from Epicor in several formats as well as any Error Information

[BoGET]
The example below makes a [GET] Request to the oData endpoint for AbcCode.

//This dictionary can be used to pass in filters to odata or any URL parameter required by the business object. It is optional
Dictionary<string, string> dic = new Dictionary<string, string>(); 
dic.Add("$top", "50");

//This will allow you pass in a CallContextHeader and more importantly receive a CallContextResponse (if you want it) it is optional
CallContextHeader callContext = new CallContextHeader(); 

var response = EpicorRest.BoGet("Erp.BO.ABCCodeSvc", "ABCCodes", dic,callContext);

//The code above returns an EpicorResponseObject (response) below are some ways to use it

// Allows you get an individual property from your response using the dynamic object
response.ResponseData.value[0].Company 

//Returns the Raw Response Body (usually JSON)
response.ResponseBody 

// Returns a boolean indicating whether there was or wasn't an error.
if(response.IsErrorResponse) 
{

      response.ResponseError; //Returns the Error Message
}

//Returns the Status Code (404) (200) etc of the Request
response.ResponseStatus 

// Contains the exception that is thrown by the server
response.BLException 

//Contains a response that was thrown specifically because of a bad client request. Something YOU did  not the server
response.BadRequest 

// Contains the exception that was thrown by RestSharp something specific like a connection issue..
response.RestCallException 

// *Note that all these 3 above are "summarized" in response.ResponseError

//Is the entire IRestSharp response object if ya want it.
response.Response 

[BoPost]
Example below makes a [POST] Request to create a new AbcCode all of the above still applies

var postData = new {
                Company = EpicorRest.Company,
                ABCCode1 = "Z",
                CountFreq = 1
            };

//Note I am passing the callcontexthere but it is OPTIONAL
var response =EpicorRest.BoPost("Erp.BO.ABCCodeSvc", "ABCCodes", postData ,callContext);

//The Response Object above has the same options as the one for [GET]

[BoPatch]
Example below makes a [PATCH] Request to update an AbcCode all of the above still applies

var patchData = new {
                Company = EpicorRest.Company,
                ABCCode1 = "Z",
                CountFreq = 1
            };

//Note I am passing the callcontexthere but it is OPTIONAL
var response =EpicorRest.BoPatch("Erp.BO.ABCCodeSvc", "ABCCodes", patchData ,callContext);

//The Response Object above has the same options as the one for [GET]

[BoDelete]
Example below deletes an ABC Code. (Using oData)

string company ="EPIC02";
string abcCode ="Z";
 response = EpicorRest.BoDelete("Erp.BO.ABCCodeSvc", $"ABCCodes('{company}', '{abcCode}')");

[BaqGet]
Example below calls a BAQ and gets the results

// Same options as standard Get apply including filtering and parameters
response = EpicorRest.BaqGet("zCustomer01");

[BaqGetDataTable]
This is a little special helper that returns a C# DataTable object with labels on columns for a given BAQ.

var  baqDt = EpicorRest.BaqGetDataTable("zCustomer01");


baqDt.Rows[0]["Customer_CustID"]

[BaqPatch]
Eample below patches a BAQ Result

var baqData = new
            {
                Customer_CustNum = 33,
                Customer_CustID = "Larry",
                SysRowID = new Guid("473e5374-fac8-47ab-abb8-fe3acd9ec77c"),
                RowMod = "U"
            };
            response = EpicorRest.BaqPatch("updatableBAQ01", baqData);

[FunctionPost]
Example below calls an Epicor function

 var smsSend = new
            {
                ToPhone = "90445555555",
                ToMsg = "Rest is so Cool!"
            };
var rsp = EpicorRest.EfxPost("FacilityPaging", "SendSMS", smsSend);

You can also wrap any of the above calls into a single Epicor Session by using the EpicorRestSession object and wrapping your call around it.

using (EpicorRestSession ses = new EpicorRestSession())
            {
                var smsSend = new
                {
                    ToPhone = "90445555555",
                    ToMsg = "Rest is so Cool!"
                };
                var rsp = EpicorRest.EfxPost("FacilityPaging", "SendSMS", smsSend);
            }

If there are any questions issues or concerns let us know!

if there is anything from the Legacy implementation that is critically missing from the overhaul let us know and we’ll take it into consideration. If you are starting out new I would highly recommend using the latest methods but set the API version to V1 if you are constrained to that for some reason.

Updates Version 2.1.0.3

Added Timeout property in MS (if specified)

EpicorRest.Timeout = 10000;
25 Likes

Remember you can also disable API key requirements in config if that’s a roadblock to using V2

You guys are legends! :+1:

2 Likes

5 Likes

All right this is live now! Testers needed :stuck_out_tongue:

I’m fairly convinced that if this site did not exist, or the people running didn’t do awesome stuff like this, that Epicor would go under or not be anywhere near as successful as it is.

I mean, I would bail and find another line of work if it weren’t for all of you.

12 Likes

I will do so tomorrow. I’ve got some projects I started that would be easily convertable.

1 Like

Love to help, but no Epicor environments to test in at the moment. :frowning:

I am testing out the library and I had some issues.

I am trying to call the BaqGetDataTable method but it is returning null under certain error situations. If I set VS to catch all exceptions there is a JsonReader exception thrown within the BaqGetDataTable call.

The setup

            EpicorRest.AppPoolHost = "server address eg domain.com"; 
            EpicorRest.AppPoolInstance = "Test";
            EpicorRest.APIKey = "the api key GUID"; 
            EpicorRest.UserName = "user"; 
            EpicorRest.Password = "password"; 
            EpicorRest.Company = "company"; 
            EpicorRest.IgnoreCertErrors = true;

then I call the method with

var response = EpicorRest.BaqGetDataTable("RestTest");

Turns out the “RestTest” BAQ was not shared so I was not able to access it. The method returned null so there was nothing to help me there. The give away was some events created on the server.

I also noted that if I had the wrong host the method would also return null but the time with no events on the server to guide me it was harder to track down.

Brett

Let me take a look it should have shown you an error in the response

Is there a sample resource that uses this? @josecgomez

There are a ton of examples above what are you looking for?

I’m trying to make my first application to create a receipt entry. I’m only seeing snippets. I was wondering if there was a full application that shows start to finish using Epicor Rest API. I’m venturing away from Service Connect and want to get acquainted to using REST

You may find calling Epicor Functions via REST a more satisfying experience. You encapsulate the Epicor logic away from your REST client making it less brittle to changes. Performance will be better as you’ll send less traffic across the wire too. Just food for thought.

1 Like

If you are new to REST perhaps doing a generic non Epicor example might be better. There are tons of examples online. This way you can see how to use REST, before you add the Epicor layer.

1 Like
4 Likes

I’ve used REST and API’s before. Just not with Epicor.

@BlakeW did you attend Insights? I presented on how to use this.

I did not unfortunately

Crap… I can’t send you my slides then, but I imagine if you search the forum for something like “EpicorRest.AppPoolHost” or “.BaqGet(” you might find references from other peoples posts. Sorry about that.

1 Like