WCF CommunicationException без подробностей сообщения об исключении - PullRequest
4 голосов
/ 13 сентября 2011

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

Например, если у меня есть следующий код сервера

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
    public DTO GetDTO()
    {
        DTO dto = new DTO();
        dto.dto = dto;
        return dto;
    }

}

public class DTO
{
    public DTO dto;
}

[ServiceContract]
public interface IServer
{
    [OperationContract]
    DTO GetDTO();
}

Я специально ввел ObjectGraph, чтобы вызвать исключение сериализации при возврате объекта DTO.

Если яу меня есть клиент, который вызывает метод этого сервера GetDTO(), я получу следующее CommunicationException.

Соединение с сокетом было прервано.Это может быть вызвано ошибкой обработки вашего сообщения или превышением тайм-аута приема удаленным хостом, или проблемой основного сетевого ресурса.Тайм-аут локального сокета был '00: 00: 58.9350000 '.

Что абсолютно бесполезно.У него нет внутреннего исключения и даже сообщения о реальном исключении.

Если вы затем используете Microsoft Service TraceViewer, вы увидите исключение, но для этого необходимо включить трассировку диагностики.

сообщение об исключении, которое следует отправить обратно:

Произошла ошибка при попытке сериализации параметра http://tempuri.org/:GetDTOResult. Сообщение InnerException было «Граф объекта для типа« TestWCFLib.DTO »содержит циклы и не можетбыть сериализованным, если отслеживание ссылок отключено. '.Пожалуйста, смотрите InnerException для получения более подробной информации.

Так кто-нибудь может сказать мне, как получить правильное сообщение об исключении, отображаемое на стороне клиента?Очевидно, что установка IncludeExceptionDetailInFaults в значение true не имеет значения.

1 Ответ

2 голосов
/ 04 декабря 2012

Я думаю, что именно из-за того, что ошибки сервера не распространяются на клиента. В целом, это практика, которая заключается в том, чтобы не раскрывать внутренние компоненты сервера клиентам, так как основной целью архитектуры Client Server является независимость от сервера.

Этого можно добиться, используя Fault Exception

Украсьте свою декларацию об обслуживании договором о неисправности

[ServiceContract]
public interface IServer
{
    [OperationContract]
    [FaultContract(typeof(MyApplicationFault))]
    DTO GetDTO();
}

Затем перехватить ошибки в реализации servcie и выдать исключение ошибки.

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class Server : IServer
    {
        public DTO GetDTO()
        {
            try
              {
                   DTO dto = new DTO();
                   dto.dto = dto;
                   return dto;
               }
            catch (Exception ex)
                 {
                     MyApplicationFault fault = new MyApplicationFault(...);
                     throw new FaultException<MyApplicationFault>(fault);
                 }
        }

    }

И перехватить исключение в клиенте

IServer proxy = ...;    //Get proxy from somewhere
try 
{
    proxy.GetDTO();
}
catch (TimeoutException) { ... }
catch (FaultException<MyApplicationFault> myFault) {
    MyApplicationFault detail = myFault.Detail;
    //Do something with the actual fault
}
catch (FaultException otherFault) { ... }
catch (CommunicationException) { ... }

Надеюсь, это поможет. Для хорошего руководства, пожалуйста, смотрите Руководство по проекту кода на исключение ошибок

...