AX.ManagedInterop.Session .Logon fails in BackgroundWorker

Hi.

We are using managed host to use WPF custom controls inside AX 2012 R3 CU10 Form.

I am trying to get data from AX from the ViewModel of a WPF control using a BackgroundWorker. It is critical to use that as it is a long operation that freezes the UI.

The problem is that the AX.ManagedInterop.Session.Current is null on that thread.

So I try to connect again using

Microsoft.Dynamics.AX.ManagedInterop.Session axs = new Microsoft.Dynamics.AX.ManagedInterop.Session();

axs.Logon(“ic1”, “en-US”, null, “AX12310_GPBD_ISV”);

if (axs.isLoggedOn())
{

result = Dal.GetAllResources();

}

This throws an InvalidLogonInSingleSessionException.

I can not find any specific details of why the logon is invalid.

Any help welcome.

Why are you trying to create a new session? The control will always be used in an existing user session.

Because I want to be able to call AX in a different thread than the one the control is on, the one that the BackgroundWorker executes on.

On that thread I don’t have a session.

The control’s thread is the same with the UI thread. Anything done there freezes the UI.

What exactly happened when you used another thread without trying to create an additional connection to AX? It’s still executed inside the process of Dynamics AX, isn’t it?

Microsoft.Dynamics.AX.ManagedInterop.Session.Current is null.
And trying to call the AX method throws null exception because the session object used is null.

Maybe this will clarify.

In the view I do this:
BackgroundWorker bw = BackgroundWorker();
private void MethodToTriggerLongRunningAction()
{
bw.DoWork+=bw_DoWork;
bw.RunWorkerAsync();
}

private void bw_DoWork(object sender, BackgroundWorkerEventArgs e)
{
try
{
Microsoft.Dynamics.AX.ManagedInterop.Session axs =
new Microsoft.Dynamics.AX.ManagedInterop.Session();

axs.Logon(“ic1”, “en-US”, null, “AX12310_GPBD_ISV”);

if (axs.isLoggedOn())
{

result = Dal.GetAllResources();

}
}
}

I tried every combination with the Logon parameter but none seems to work.

What code did you use when you called the method directly instead of trying to create another sessions the AX client process? Just result = Dal.GetAllResources()? I assume that Dal is an AX proxy class, correct?

If the thread doesn’t see the session, I think you should refer to the current session of the main thread instead of trying to create a new one. Don’t forget that object references can be shared across threads.

I may be wrong, because I don’t know how it works internally, but I would be surprised if your code worked. I believe that it would make sense if you used it from another process, but not for trying to create a new user session inside another. Maybe it’s what InvalidLogonInSingleSessionException is trying to tell you.

Yes , Dal is a AX proxy class.

I tried referring to the other session , but I got an error. Something like it is not allowed , I will have to retry to get the exact text , but it looked to me like it was forbidden on purpose to reuse the session from another thread.

What I can’t explain is why if I use the exact same code but host the controls inside a WPF window everything works fine. I don’t even need to specify parameters , I can call with axs.Logon(null, null, null, null); and it works.

You would have to tell me what you mean by “WPF window”. Knowing what UI framework you used doesn’t tell me anything about which process you’re talking about. If it’s a separate application, it just proves my point.

By WPF Window I mean a separate WPF application.
Can you explain your point?
I tried a simple console application with only a reference to Microsoft.Dynamics.AX.ManagedInterop

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Logon if necessary (e.g. when running in WPF project).
if (Session.Current == null)
{
Session axSession = new Session();

if (!axSession.isLoggedOn())
{
axSession.Logon(null, null, null, null);
}
Console.WriteLine(axSession.isLoggedOn().ToString());
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync();
Console.ReadLine();
}
}

static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine(e.Result.ToString());
}

static void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (Session.Current == null)
{
Session axSession = new Session();

if (!axSession.isLoggedOn())
{
axSession.Logon(null, null, null, null);
}

e.Result = "from background worker: " + axSession.isLoggedOn();

}
}
}
}
Output:
True
from background worker: True

Basically it creates a session both on the main thread and in the background thread.

But this does not work if the background worker is created by a WPF control hosted inside the AX form.

I’m saying this is intended for communication between processes, so when you use from a different application, you’re doing the right thing. Your application became a kind of AX client, you create a user sessions and start communications with AOS. It’s as intended and it works.

But if you try to do the same from inside the AX client (and its already running user session), it’s clearly a completely different situation. I would expect it to fail, so it wasn’t a big surprise for me that you got an exception.