简体   繁体   中英

WCF service Cannot catch a client's crash

I've created a WCF service which uses a NetTCP binding.

My service is accessed by a client, saves its callback channel and uses it to call the client later on (it's a persistent tcp connection). Everything works fine, but if I decide to suddenly kill the client - I get a SocketException which I can't catch ("An existing connection was forcibly closed by the remote host").

What have I already tried?

  1. I've added try-catch clauses in every method using the callback channel, and even in the upper level - the WCFHost which starts my service.

  2. I've tried getting both the channel and the callback channel and adding a method treating the channel faulted event:

     var channel = OperationContext.Current.Channel; channel.Faulted += ChannelFaulted; var callbackChannel = OperationContext.Current.GetCallbackChannel<CallbackInterface>(); var comObj = callbackChannel as ICommunicationObject; comObj.Faulted += ChannelFaulted; 

In short, I'm trying to handle exceptions thrown by the client - on the server side.

There are two ways for a WCF service to support exception handling:

1.Defining the serviceDebug.includeExceptionDetailInFaults attribute to “true” in the hosts .config file 2. Defining the includeExceptionDetailInFaults attribute to “true” on the service class.

Example:

Config File Solution:

<behaviors>
<serviceBehaviors>
<behavior name=”ServiceBehavior”>
<serviceMetadata httpGetEnabled=”true”/>
<serviceDebug includeExceptionDetailInFaults=”true”/>
</behavior>
</serviceBehaviors>
</behaviors>

Attributed Class Solution:

[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CustomersService : ICustomersService
{
private CustomerDetail customerDetail = null;

… etc

Throwing the Exception Setting the includeExceptionDetailInFaults to true is your first step in supporting exceptions in WCF.

The next step is to have your service throw the FaultException exception (a class in the System.ServiceModel.FaultException namespace). Note that you cannot expect to simply use the typical Exception class when you wish to throw exceptions from the WCF host to the WCF client. To throw exceptions over the WCF bindings you will need to use the FaultException class.

Throwing FaultException Example :

try
{
//Try to do stuff
}
catch
{
throw new FaultException(“Full ruckus!”);
}

Catching FaultException Example :

Now the WCF client can catch the FaultException…

try
{
//Client calls services off the proxy
}
catch(FaultException fa)
{
MessageBox.Show(fa.Message);
}

Distinguish Types of Fault Exceptions The FaultException class is a generic class for WCF exceptions. In order to determine what type of FaultExceptions occur, you use the FaultCode class. On the WCF service the FaultCode implementation will look something like this:

try
{
   //Connect to a database
}
catch
{
   throw new FaultException(“Full ruckus!”, new FaultCode(“DBConnection”));
}

On the WCF client, the FaultCode implementation will look something like this:

 try
    {
       //Call services via the proxy
    }
    catch(FaultException fa)
    {
       switch(fa.Code.Name)
       {
         case “DBConnection”:
           MessageBox.Show(“Cannot connect to database!”);
           break;
         default:
           MessageBox.Show(“fa.message”);
           break;
        }
    }

for more information you can look here and also here

After much investigation it turns out that a server can detect exceptions thrown by the client using the Faulted event I mentioned earlier in my question (I should have been more patient when debugging, and wait until the exception "climbed" all levels until getting to my code).

Please note, however, that the event catches the exception only when it is too late: the channel is already null (and so is the OperationContext.Current). I couldn't catch the original SocketException thrown by the System.ServiceModel.dll even when I tried using the IServiceBehavior and the IEndpointBehavior (which set an IChannelInitializer). When my ChannelFaulted() method was finally called, there was no way to detect which client failed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM