Служба WCF не может поймать сбой клиента

Я создал службу WCF, которая использует привязку NetTCP.

Клиент получает доступ к моей службе, сохраняет свой канал обратного вызова и использует его для последующего вызова клиента (это постоянное соединение TCP). Все работает нормально, но если я решаю внезапно убить клиента - я получаю исключение SocketException, которое не могу поймать ("Существующее соединение было принудительно закрыто удаленным хостом").

Что я уже пробовал?

  1. Я добавил предложения try-catch в каждый метод, использующий канал обратного вызова, и даже на верхнем уровне - WCFHost, который запускает мой сервис.

  2. Я попытался получить как канал, так и канал обратного вызова и добавить метод, обрабатывающий событие сбоя канала:

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

Короче говоря, я пытаюсь обрабатывать исключения, выдаваемые клиентом - на стороне сервера.

2 ответа

Решение

После долгих исследований выясняется, что сервер может обнаруживать исключения, генерируемые клиентом, используя событие Faults, о котором я упоминал ранее в своем вопросе (я должен был быть более терпеливым при отладке и ждать, пока исключение не "переместится" на все уровни, пока не достигну код).

Обратите внимание, однако, что событие перехватывает исключение только тогда, когда оно слишком поздно: канал уже нулевой (как и OperationContext.Current). Я не мог поймать оригинальное SocketException, выданное System.ServiceModel.dll, даже когда я попытался использовать IServiceBehavior и IEndpointBehavior (которые устанавливают IChannelInitializer). Когда мой метод ChannelFaults () был наконец вызван, не было никакого способа определить, какой клиент потерпел неудачу.

Для службы WCF существует два способа поддержки обработки исключений:

1. Определение атрибута serviceDebug.includeExceptionDetailInFaults в "true" в файле hosts.config. 2. Определение атрибута includeExceptionDetailInFaults в "true" в классе обслуживания.

Пример:

Конфигурация файла Решение:

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

Приписываемое решение класса:

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

… так далее

Бросок исключения Установка для параметра includeExceptionDetailInFaults значения true - это ваш первый шаг в поддержке исключений в WCF.

На следующем этапе ваша служба выдает исключение FaultException (класс в пространстве имен System.ServiceModel.FaultException). Обратите внимание, что вы не можете рассчитывать на простое использование типичного класса Exception, если вы хотите выбросить исключения из хоста WCF в клиент WCF. Чтобы бросить исключения в привязки WCF, вам нужно использовать класс FaultException.

Throwing FaultException Пример:

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

Пример Catching FaultException:

Теперь клиент WCF может поймать FaultException...

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

Различают типы исключений ошибок Класс FaultException является универсальным классом для исключений WCF. Чтобы определить, какой тип FaultExceptions происходит, вы используете класс FaultCode. В службе WCF реализация FaultCode будет выглядеть примерно так:

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

На клиенте WCF реализация FaultCode будет выглядеть примерно так:

 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;
        }
    }

Для получения дополнительной информации вы можете посмотреть здесь, а также здесь

Другие вопросы по тегам