I’ve searched the forum and did not find anything. I am in a data directive and trying to set up a REST call but I am not finding Epicor.Ice.Lib.RestClient.dll. Is it something else in 500?
I think it was shipped in 600, but you can use any old HTTP client you want to call a RESTful API
Hmmmmmmmm, interesting. Very unfortunate as I now need to figure out how to do that without the helpers in 600.
Thanks for letting me know @Aaron_Moreng
happy to help, let me know if you get stuck
Are you trying to call a function?
Methods. Specifically Erp.QuoteAsm.ChangeOpDtlResourceGrpID, Erp.QuoteAsm.ChangeOpDtlResourceID, and Erp.QuoteAsm.Update
AH! Don’t use REST!!!
REST should only be used externally (from outside Epicor) if you are inside Epicor use the BO’s directly WAYYYYYYYYYYYYYYYYYYYYYYYYYYYYY Cheaper. (Performance Wise)
Architecturally speaking REST sits in between the Facade and the Epicor BO’s
Also to use REST you have to go through the HTTP protocol (network) which is expensive.
If you are in a Data Directive that’s the equivalent of getting up from your livin-groom walking out of the house getting in your car driving to Walmart and back going around the house coming in the back door and walking into your dinning room to eat dinner.
VS going directly to either Db.XX or the BO via ServiceRenderer that’s akin to walking from Livingroom to dinning room.
Technically speaking if you use Db.XX you are already in your dinning room and just reaching out for your plate…
ServiceRenderer still needs you to get up and walk a bit.
Lol! I’m such a hack!!! Thank you @josecgomez
What I am trying to do is this.
We have a cellular environment for manufacturing and do not have the advanced scheduling (or whatever gives you capabilities). We also have a quoting program that is interfaced with Epicor and will be importing the MOM. So, I am trying to use some logic to change the resource when it comes in to the “correct” resource. We did not want to double all of the operations, so I am attempting to get it done through a customization. I have figured out that I have to do it in a DD because the OpDtl records get saved after the Post-Processing Update. I thought I had to do it In-Transaction.
Can I do this through a Standard DD? Let the data save and then make the changes? I did not think that was a good way, but I proved how much of a hack I was above. Will the Standard fire before whatever the next method is being called in the integration?
You can do it as an In-Transaction DD, or better yet do it as a Post Processing on the Update mechanism in a standard method directive.
You should be able to in post Processing afterthe Operation is created, lookup the “created” OpDtl record, change the resource and re-save.
Well, I have been at this for days and I was originally going the route @josecgomez suggests. But I have hit so many walls I started looking elsewhere.
I think I finally figured out what the wall was, 2 records are in the ds.QuoteOpDtl instead of just 1. Has anyone ever seen this before?
Because only one record is saved to the database.
If you know how to use the BL Tester you can see what the two records are.
Otherwise you may be able to index your DS. Something like ds.QuoteOpDtl.Tables[0].Something
Jose, I am trying to directly call a function in code, but from what I understand this can only be done using REST. I am inside the smart client.
So if we are only to use REST externally (from outside of Epicor) how would you directly call a function using c#?
-Utah
You have to do it making a web request. In 700+ there’s a helper library.
You can add the REST Nuget and call it that way, or you can use webrequest which requires no external DLL.
Web Request
private string InvokeFunction(string lib,string funcName)
{
var pi = typeof(Ice.Core.Session).GetField("encryptedPassword", BindingFlags.Instance|BindingFlags.NonPublic).GetValue(oTrans.Session);
var pt = typeof(Ice.Core.Session).GetMethod("decrypt", BindingFlags.Instance|BindingFlags.NonPublic).Invoke(oTrans.Session, new[]{pi});
string auth = string.Format("{0}:{1}",((Ice.Core.Session)oTrans.Session).UserID, pt.ToString());
auth = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(auth));
var webRequest = System.Net.WebRequest.Create(string.Format("https://84799-e10-test.epicorhosting.net/EpicorF_SSL500/api/v2/efx/staging/C001/{0}/{1}",lib,funcName));
webRequest.Method ="POST";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("Authorization", "Basic "+ auth);
webRequest.Headers.Add("x-api-key", "oYwmrv7RKd7BbrfX3EaDzzsKKHRt4XztMVOY2rwxO1qpa");
using (var streamWriter = new System.IO.StreamWriter(webRequest.GetRequestStream()))
{
string json="{ \"input\":\"Jose\" }";
streamWriter.Write(json);
}
var httpResponse = (System.Net.HttpWebResponse)webRequest.GetResponse();
string result="";
using (var streamReader = new System.IO.StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return result;
}
Usign the REST Nuget
public bool SetupEpicorRest(string apiKey)
{
try
{
string appUri =AppSettingsHandler.GetValue(AppSettingsSections.Application, "AppServerURL", null);
var uri = new Uri(appUri);
EpicorRest.AppPoolHost=uri.Host;
EpicorRest.AppPoolInstance = uri.LocalPath.Replace("/","");
EpicorRest.APIKey = apiKey;
var session = oTrans.Session as Ice.Core.Session;
var accessTokenFunc = typeof(Ice.Core.Session).GetProperty("GetAccessTokenFunc", BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public).GetValue(session) as Func<bool,string>;
if(accessTokenFunc !=null)
{
EpicorRest.BearerToken = accessTokenFunc(false);
}
else if(Epicor.ServiceModel.Bindings.BindingName.IsSingleSignOn(AppSettingsHandler.GetValue(AppSettingsSections.Application, "EndpointBinding", null)))
{
EpicorRest.UserName = Environment.UserName;
EpicorRest.Password = "";
}
else
{
object clientCreds = typeof(Ice.Core.Session).GetProperty("ClientCredentials", BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public).GetValue(session);
if(clientCreds!=null)
{
object clientCredsUname = clientCreds.GetType().GetProperty("UserName").GetValue(clientCreds);
EpicorRest.UserName =clientCredsUname.GetType().GetProperty("UserName").GetValue(clientCredsUname) as String;
EpicorRest.Password =clientCredsUname.GetType().GetProperty("Password").GetValue(clientCredsUname) as String;
}
}
return true;
}
catch(Exception ex)
{
return false;
}
}
if(SetupEpicorRest("APIKeyHere"))
{
EpicorRest.EfxPost("", "", new { });
}
Thank you Jose, I am still in 500… is your code still kosher for 500?
It is specifically for 500 the first code doesn’t require external DLL…
The second code requires the Rest nuget
Thank you
Jose, do we need to close our streamwriter and/or streamreader’s?
Is that necessary and proper or can you do whatever?
using (var streamWriter = new System.IO.StreamWriter(webRequest.GetRequestStream()))
using (var streamReader = new System.IO.StreamReader(httpResponse.GetResponseStream()))
{