Showing posts with label Proxies. Show all posts
Showing posts with label Proxies. Show all posts

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.