This is what I figured I could do on the Client Side… It works and has been working for a few months now! Flawless
Save this Snippet! Took Days to get right! Runs and honors Session Licensing timeouts etc… Also instead of managing another Service Account, I used the “Agent User” a method discovered in the MRP Engine. Works like a charm!
I did a study on the Sessions in Admin Console, I did a full SPIKE took 7 days to Test / Document Behaviours, it all ran super! It ran fast! I could even Create a Session between each BAQ Call… But I decided to Create one when the Form Loads and leave it.
// Session Impersonation Vars
Ice.Core.Session newSession;
// InitCustomCode
this.newSession = this.GetNewSessionAsSysAgent();
// DestroyCustomCode
// Begin Custom Code Disposal
Ice.Proxy.Lib.SessionModImpl sMod = GetInstanceField(typeof(Ice.Core.Session), newSession, "sessionMod") as Ice.Proxy.Lib.SessionModImpl;
sMod.Logout();
this.newSession = null; // Do NOT Dispose it, it will kill Epicor
// We need a Session Link to 003 which Local Users
// may not have access to - lets Auth as Agent
// could be refactored a bit
public Ice.Core.Session GetNewSessionAsSysAgent()
{
string username = string.Empty;
string password = string.Empty;
object searchReslts = ProcessCaller.PerformSearch(oTrans.EpiBaseForm, "SysAgentAdapter", "Rows", string.Empty);
if (searchReslts is DataSet) {
DataSet searchDS = (DataSet) searchReslts;
if (searchDS.Tables[0].Rows.Count > 0) {
username = searchDS.Tables["SysAgent"].Rows[0]["SysUserID"].ToString();
password = searchDS.Tables["SysAgent"].Rows[0]["SysPassWord"].ToString();
}
}
if (username != string.Empty && password != string.Empty)
{
try {
return new Ice.Core.Session(username, Epicor.Security.Cryptography.Encryptor.DecryptToString(password));
}
catch (Exception ex)
{
EpiMessageBox.Show("Unable to Authenticate with Company MAIN.\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return null;
}
internal static object GetInstanceField(Type type, object instance, string fieldName)
{
BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Static;
FieldInfo field = type.GetField(fieldName, bindFlags);
return field.GetValue(instance);
}
public System.Data.DataSet GetBAQDataSetDataTagFromMainCompany(string partNum, string partRev)
{
if (newSession == null)
{
MessageBox.Show("Unable to Authenticate with Company MAIN, Please See System Administrator");
return null;
}
using (this.oTrans.PushDisposableStatusText("Initializing Global Query...", true))
{
ILauncher iLnch = new ILauncher( newSession );
//removeEventhandlers(newSession); // Done Globally
using (var newTransaction = new EpiTransaction(iLnch))
using (var adapterDynamicQuery = new DynamicQueryAdapter(newTransaction))
{
adapterDynamicQuery.BOConnect();
// Declare and Initialize Variables
string BAQName = "SMI-zGetDataTagByPartRev";
Ice.BO.QueryExecutionDataSet ds = new Ice.BO.QueryExecutionDataSet();
// Add Parameter Rows
ds.ExecutionParameter.AddExecutionParameterRow("PartNum", partNum, "nvarchar", false, Guid.Empty, "A");
ds.ExecutionParameter.AddExecutionParameterRow("RevisionNum", partRev, "nvarchar", false, Guid.Empty, "A");
// Call Adapter method
adapterDynamicQuery.ExecuteByID(BAQName, ds);
System.Data.DataSet results = adapterDynamicQuery.QueryResults;
return results;
}
}
return null;
}
Thanks @Rich and @Bart_Elia and @josecgomez and @Chris_Conn for poking at this a while back.
PS: Chris looks like sMod.Logout() was the only save way, removing the Session Event Listeners ruined other Screens / Avalara Tax etc… Good find.
DISCLAIMER: I do not do this on every form, in every case. We utilize Service Connect heavily! There are those 1 or 2 Cases where this is used, as we move to APIs, we didnt want to invest in more SC Workflows as we are phasing it out slowly.