Monday, June 14, 2010

Working with Proxies and the Ambiguous “No .NET Business Connector session could be found” or “Cannot access a disposed object” Errors

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.

No comments:

Post a Comment