Thomas
Thomas

Reputation: 1126

exception handling for wcf service

i am currently developing a wcf publish subscribe service. On my windows form app, I have a Connect button that attempts to subscribe to the service. the code is as follows

WSDualHttpBinding binding = (WSDualHttpBinding)client.Endpoint.Binding;
string clientcallbackaddress = binding.ClientBaseAddress.AbsoluteUri;
clientcallbackaddress += Guid.NewGuid().ToString();
binding.ClientBaseAddress = new Uri(clientcallbackaddress);

InstanceContext site = new InstanceContext(null, new mainForm(backgroundFormObject));
PostingContractClient client = new PostingContractClient(site);

client.Subscribe();
MessageBox.Show("Service has been connected!", "Connected");

as for the exception handling, this is what i have done,

try
{
    //refer to codes above
}
catch (EndpointNotFoundException)
{
    MessageBox.Show("WCF Service has not been started.", "Error");
}
catch (CommunicationException)
{
    MessageBox.Show("Error");
}

if my service is not activated, upon clicking the Connect button, it will load for awhile before sending the first error, "WCF Service has not been started." , after which I activate the service, clicking the Connect button shows me the second error, which is CommunicationException despite my service being on.

Any idea how to fix this?

The error message for the error

The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

Upvotes: 1

Views: 1750

Answers (3)

ericlee
ericlee

Reputation: 2753

Not sure if this is what you want, but from what I can understand from your question this seems like what you need:

Since you need the variable to be available throughout the whole project, you can declare the InstanceContext and the Client at the start of the the class.

InstanceContext site;
PostingContractClient client;

follow by in the form_Load method,

site = new InstanceContext(null, new mainForm(backgroundFormObject));
client = new PostingContractClient(site);

and finally in your "Connect" button,

        try
        {
            site = new InstanceContext(null, new mainForm(backgroundFormObject));
            var client = new PostingContractClient(site);

            WSDualHttpBinding binding = (WSDualHttpBinding)client.Endpoint.Binding;
            string clientcallbackaddress = binding.ClientBaseAddress.AbsoluteUri;
            clientcallbackaddress += Guid.NewGuid().ToString();
            binding.ClientBaseAddress = new Uri(clientcallbackaddress);

            client.Subscribe();
            MessageBox.Show("Service has been connected!", "Connected");
        }
        catch (EndpointNotFoundException)
        {
            if (client != null)
            {
                MessageBox.Show("WCF Service has not been started. Please try to manually connect again after the service has been started.", "Error");

Upvotes: 1

Alexander Yezutov
Alexander Yezutov

Reputation: 3214

I'm a little bit confused the code above, and try to explain that in comments:

// The client seems to be initialized by that time
WSDualHttpBinding binding = (WSDualHttpBinding)client.Endpoint.Binding;

...

// The client is initialized again
PostingContractClient client = new PostingContractClient(site);

Anyway, from the error, you have posted, it seems, that you are trying to use the same object for both consequent calls, like:

var client = new Client();
client.Subscribe(); // you get an exception here
client.Subscribe(); // channel is faulted, as you got an exception accessing it the first time

I didn't work much with adding WCF services as references, and i don't know implementation details. But working with assembly sharing a lot, I would recommend to try to create the Client once again:

var client = new Client();
client.Subscribe(); // you get an exception here

client = new Client(); // I hope, another Channel is created, when calling the constructor.
client.Subscribe();

Best regards.

Upvotes: 1

Shiraz Bhaiji
Shiraz Bhaiji

Reputation: 65391

The problem here is that the previous call has had an error and left the communication channel in a failed state. It therefore cannot be used until it is closed.

You need to catch any errors and clean up and channel in a faulted state.

This is some standard code that we use, in your case you may not want to close the channel.

It maybe that the channel is in a faulted state since it has timedout.

        try
        {
              client.Subscribe();  
        }

        catch (Exception exception)
        {

            if (client != null)
            {
                client.Abort();
            }
            throw;
        }

        finally
        {
            if (client != null)
            {
                client.Close();
            }
        }

Upvotes: 3

Related Questions