Служба WCF не может поймать сбой клиента
Я создал службу WCF, которая использует привязку NetTCP.
Клиент получает доступ к моей службе, сохраняет свой канал обратного вызова и использует его для последующего вызова клиента (это постоянное соединение TCP). Все работает нормально, но если я решаю внезапно убить клиента - я получаю исключение SocketException, которое не могу поймать ("Существующее соединение было принудительно закрыто удаленным хостом").
Что я уже пробовал?
Я добавил предложения try-catch в каждый метод, использующий канал обратного вызова, и даже на верхнем уровне - WCFHost, который запускает мой сервис.
Я попытался получить как канал, так и канал обратного вызова и добавить метод, обрабатывающий событие сбоя канала:
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;
}
}
Для получения дополнительной информации вы можете посмотреть здесь, а также здесь