E10 in Visual Studio 2015

I decided to finally give E10 a whirl in Visual Studio. First - wow - code completion for the win.

With that said I am having some issues. I connected, authenticated, connected the Part BO.

I was able to successfully use PartExists() but if I try to use wither GetRows() or GetByID() I get the following error:
System.InvalidCastException was unhandled
HResult=-2147467262
Message=Unable to cast object of type ‘Ice.Core.Session’ to type ‘Ice.Lib.Framework.ILaunch’.
Source=Erp.Adapters.Part
StackTrace:
at Erp.Adapters.PartAdapter.get_partData()
at Erp.Adapters.PartAdapter.GetCurrentDataSet(DataSetMode dsMode)
at Ice.Lib.Framework.EpiBaseAdapter.afterGetByID(DataSet rowsDataSet)
at Ice.Lib.Framework.EpiBaseAdapter.GetByID(String stringId)
at EpicorBaseProject.Form1.button1_Click(Object sender, EventArgs e) in c:\users\cconn\documents\visualstudio2015\Projects\EpicorBaseProject\EpicorBaseProject\Form1.cs:line 44
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at EpicorBaseProject.Program.Main() in c:\users\cconn\documents\visualstudio2015\Projects\EpicorBaseProject\EpicorBaseProject\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

Here’s some of my test code:

  using (Session epiSession = new Session("Me","MyPassword",Session.LicenseType.Default, @"C:\Epicor\ERP10.1Client\Client\config\E10LiveDB2.sysconfig"))
            {
                PartAdapter pa = new PartAdapter(epiSession);
                pa.BOConnect();

                if (pa.PartExists("498CC")) MessageBox.Show("498CC exists");

                bool more;
                SearchOptions opts = new SearchOptions(SearchMode.AutoSearch);

                //PartListDataSet ds = new PartListDataSet();
               bool res =  pa.GetByID("498");
                  /*DataSet ds = pa.PartList;
                               //pa.GetRows(opts, out more);
                               //pa.PartList;
                        }

Any thoughts?

did you play the cast game?

string myPart = “498”;
bool res = pa.GetByID(myPart);

No dice for me.

I am wondering if I am passing the wrong object to the PartAdapter (even though it seems to work with PartExists())

using (Session epiSession = new Session("Me","MyPassword",Session.LicenseType.Default, @"C:\Epicor\ERP10.1Client\Client\config\E10LiveDB2.sysconfig"))
            {
                PartAdapter pa = new PartAdapter(epiSession);  // SHOULD I BE PASSING SESSION OBJECT?

Looks like this may be the culprit in EpiClientLib:

// Ice.Lib.Framework.AdapterHelper
private static System.Reflection.Assembly getAdapterAssembly(ILaunch Sender, string Adapter, out string AssemblyName)

If change the object passed to the constructor of PartAdapter, BOConnect() complains:

Additional information: Invalid request -- object Sender must be Core.Session or implement ILaunch

And for anyone reading this on pins and needles - if I ignore the exceptions and continue, things work fine. Time to catch some exceptions!

The epiSession cannot be used in the part adapter, you’ll have to use the ILauncher. See below.

EpiLaunch = New ILauncher(EpiSession)
Dim JobAdapter As New Erp.Adapters.JobEntryAdapter(EpiLaunch)

1 Like

You shouldn’t be using adapters inside of visual studio external projects since your need a launcher and a whoke bunch of dependencies.
Use the WCF services or REST services to interact with epicor from Visual Studio.
Right tool for the right job so to speak
Unless I’m missing the point if your goal
You’ll need megs upon megs of references and it will make your code VERY VERY version specific

Try this instead it’s a lot cleaner , doesn’t use the adapters and it has a lot less dependencies. IT basically instantiates the WCF BO

 public static class EpicorHelper
    {
        public static TImpl GetEpicorBOInstance<TImpl, TContract>(CustomBinding binding, Uri appServer, string userName, string password, EndpointIdentity epi = null)
            where TImpl : ImplBase<TContract>
            where TContract : class
        {

            TImpl client = (TImpl)Activator.CreateInstance(typeof(TImpl), binding, appServer, epi);
            client.ClientCredentials.UserName.UserName = userName;
            client.ClientCredentials.UserName.Password = password;

            return client;
        }
    }

Using it

CustomBinding wcfBinding = NetTcp.UsernameWindowsChannel();
using (var companyBO = EpicorHelper.GetEpicorBOInstance<CompanyImpl, CompanySvcContract>(wcfBinding, new Uri($"net.tcp://{tEpicorServer}/{EpicorInstance}/ERP/BO/Company.svc"), userName, Password,null))
{
//var x = companyBO.GetList(...etc);
}

You’ll just have to include the Erp.Contracts.BO.Company.dll (Or whichever BO you are using)
and Epicor.ServiceModel

2 Likes

Great stuff! Thanks fellas

My goal (for the moment) is the use VS for my customization development so I hope to use the adapters in the same way I would within a customization. This way after I am done with dev, I can copy it over to customization.

In that case you don’t need to run the code. It’s difficult to run the customization code. The best thing to do is use VS for writing the code and then copy the code over to test

1 Like

For the record, instanciating an ILauncher worked perfectly. No more exceptions, adapter code is working flawlessly. Thanks Matt