V3 Release Major Update 12/17/2024
This release V3 3.0.0.0 contains breaking changes from prior versions as outlined below
The biggest change in this version other than a few bug fixes is to pivot the library to be Instance friendly instead of static. The static approach while it simplified some things it made some other things quite difficult. In order to keep backwards compatibility we still have a static wrapper which should function the same as it always has, below is a breakdown of changes and how to Upgrade easily. This request came from @HLalumiere but also several other users and I have myself encountered issues with this limitation.
- EpicorRest and EpicorRestV1 are now instance classes and should be instanciated as follows
EpicorRest myEpicorRestInstance= new EpicorRest();
myEpicorRestInstance.AppPoolHost = "subdomain.domain.tld"; //TLD to your Epicor Server
myEpicorRestInstance.AppPoolInstance = "EpicorDemo700"; //Epicor AppServer Insdtance
myEpicorRestInstance.UserName = "epicor"; //Epicor Username
myEpicorRestInstance.Password = "epicor"; //Epicor Password
myEpicorRestInstance.APIKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //API key required with V2
myEpicorRestInstance.Company = "EPIC03"; //Epicor Company (Current company) Required with V2
myEpicorRestInstance.APIVersion = EpicorRestVersion.V2; //Defaults to V2
myEpicorRestInstance.License = EpicorLicenseType.Default; // You can select the type of license you want to use for the call.
The above approach allows you to have multiple instances of EpicorRest without stepping on each other, it also allows you to maintain multiple Sessions.
2. When instantiating a Session you now need to pass in the instance you’d like to associate with the session as shown below
EpicorRest myEpicorRestInstance= new EpicorRest();
//snip....
using (EpicorRestSession ses = new EpicorRestSession(myEpicorRestInstance))
{
var smsSend = new
{
ToPhone = "90445555555",
ToMsg = "Rest is so Cool!"
};
var rsp = EpicorRest.EfxPost("FacilityPaging", "SendSMS", smsSend);
}
Again this allows you to have multiple instances and multiple sessions going at once.
- When instanciating CallContext you’ll also have to pass in the instance because the client contains information like username company etc.
EpicorRest myEpicorRestInstance= new EpicorRest();
//snip....
CallContextHeader callContext = new CallContextHeader(myEpicorRestInstance);
The above change also hilights a new class that was added to the project called EpicorCommon which is inherited by both EpicorRestV1 and EpicorRestV2 so each of these instances is in fact an instance of EpicorCommon
4. EpicorRestStaticWrapper class was created as a static wedge instance for backwards compaitbility. To easily upgrade any project without making any changes simply replace EpicorRest.XX with EpicorRestStaticWrapper.EpicorRest.XX and it should be seemless.
.NET Framework: NuGet Gallery | EpicorRestAPI 3.0.0
.NET Core 6+ NuGet Gallery | EpicorRESTAPICore 3.0.0
.NET Standard 2.1 NuGet Gallery | EpicorRESTAPIStandard 3.0.0
@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;