Recently, I created an X++ class with a series of methods that I wanted to be able to access via a Web Part in Enterprise Portal.
Microsoft’s documentation on Proxies provided a good basis for setting this up.
The problem however came in using the following using block to wrap the code calling the X++ method:
Everything worked great, that was until I used the same block in two different events (called during the same page load) to call another X++ method. It wasn’t immediately clear what was going on, because my page started throwing the ambiguous error “
No .NET Business Connector session could be found”, which led me to believe that I either broke something in my code, or that Enterprise Portal was acting quirky.
using (IAxaptaAdapter a = this.AxSession.AxaptaAdapter)
{
…
}
As I would eventually find out, attempting to obtain a new session, for example, by using the helper function (below) more than once during a given page load, is where the trouble resides. The first time you get the session, everything is great; however the second time, the session is returned as null, which effectively causes the problem.
private ISession AxSession
{
get
{
AxBaseWebPart webpart = AxBaseWebPart.GetWebpart(this);
return webpart == null ? null : webpart.Session;
}
}
The simplest way to setup this error-producing scenario is to call this using block two times in a row, using similar code as seen below. Everything works great stepping through the first block, but the page blows up during the second.
protected void Page_Load(object sender, EventArgs e)
{
using (IAxaptaAdapter a = this.AxSession.AxaptaAdapter)
{
MyCustomClass test = new MyCustomClass(a);
string s = test.myCustomFunction();
}
using (IAxaptaAdapter a = this.AxSession.AxaptaAdapter)
{
MyCustomClass test = new MyCustomClass(a);
string s = test.myCustomFunction();
}
}
Even more ugly is the error that is thrown if you attempt to use the using code block on a web control that has an AxDataSource, this error actually reveals the root problem behind the previous error.
[ObjectDisposedException: Cannot access a disposed object.]
The solution to both errors is rather simple. Setup your IAxaptaAdapter as a global variable in your class, and establish the session only one time during your Page_Load event.
public partial class myClass : System.Web.UI.UserControl
{
private IAxaptaAdapter axapta;
private ISession AxSession
{
get
{
AxBaseWebPart webpart = AxBaseWebPart.GetWebpart(this);
return webpart == null ? null : webpart.Session;
}
}
protected void Page_Load(object sender, EventArgs e)
{
axapta = this.AxSession.AxaptaAdapter;
…
You will then be able to access the session multiple times, for example, you could call your X++ method in the page load event, and later in the Button1_Click event.
protected void Page_Load(object sender, EventArgs e)
{
axapta = this.AxSession.AxaptaAdapter;
MyCustomClass test = new MyCustomClass(axapta);
string s = test.myCustomFunction();
}
protected void Button1_Click(object sender, EventArgs e)
{
Tmt_CallReportClass test = new Tmt_CallReportClass(axapta);
string s = test.myCustomFunction();
}
This will also allow you to have a AxDataSource control on the page, without any issues.