tags:

views:

23

answers:

2

I have an ASP.net page that is creating a service reference to a WCF service and making calls in multiple places in my page. I instantiate the service reference in Page_Load and have an instance variable to store it:

private FooClient _serviceClient;

protected void Page_Load(object sender, EventArgs e)
{
    _serviceClient = nwe FooClient();
    _serviceClient.GetAllFoos();
}

protected void btnSave_Click(object sender, EventArgs e)
{
    _serviceClient.SaveFoo();
}

I just discovered that I need to be disposing of the service reference when I am done using it or else the connections will be kept alive and will block incoming connections if I reach the max number of connections. Where would the best place to dispose of these references be? I was thinking of doing it on the OnUnLoad event.

Is there a better way of doing this?

A: 

according to MSDN documentation and personal experience do something as follows:

 try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

this would allow the correct closing or abortion of the service when necessary rather than leaving them to be disposed at a predefined time - only keep the connection open as long as you definately have to. personally i dont like inheriting from IDisposable as its very heavy in performance

PaulStack
Why is inheriting from `IDisposable` heavy in performance??
Ronald Wildenberg
So you're suggesting that I open a channel in every method that I need to access data? That seems pretty heavy in performance.
Dismissile
@Dismissile - why keep a connection open rather than just open it when needed? would you keep a connection to the database open if its not being used? surely the aim is to keep the connections free for use when possible therefore just open when necessary.also WCF services can throw exceptions on Dispose() and therefore the garbage collector will have to clean up the connection. If the code looks ugly im sure it can be re-factored to keep the code DRY
PaulStack
@Ronald Wildenberg I was referring to the fact that implementing IDisposable in a WCF application may meant that when called the Dispose method may not be called thus it will still need garbage collected - therefore the implementation of this is not necessary. The way we can get around this is to override the IDisposable method and then call the close or abort from it
PaulStack
Dismissile
In my opinion yes - there is no way for sure that we can depend on Page UnLoad being called or a lifecycle method being called where the service can be disposed.
PaulStack
+1  A: 

Personally, I would open FooClient when I need it, so not in Page_Load but in the methods that do web service calls. This way, you know exactly what happens to it. I usually take the following approach:

var client = OpenClient();
try
{
    // Perform operation(s) on client.
}
finally
{
    CloseClient(client);
}

This way you are sure you close your proxy, whatever happens (if there are exceptions you need to catch, simply add a catch clause). The CloseClient method should look like the one in PaulStack's answer.

Another benefit you get when you do this is that multiple calls don't interfere with eachother. Suppose one of you web service calls leads to an unexpected exception. The client channel is now in a faulted state and therefore unusable for any other calls.

And third, suppose an exception does occur that you can not catch or do not want to catch, I'm not sure Page_Unload is actually called (and I don't know what page method will be called in that event). This will also leave connections open.

Ronald Wildenberg