Ловит исключение связи вместо пользовательского исключения ошибки - WCF - PullRequest
1 голос
/ 26 апреля 2010

На сервере я выкидываю исключение, подобное этому.

catch(SqlException exception)
{
  if (exception.Message.Contains("Custom error from stored proc"))
  {
    //Exception to be thrown when authentication fails.
    throw new FaultException<MyServiceFault>(new MyServiceFault { MessageText = exception.Message });
  }
}

И на стороне клиента я ловлю исключение

catch(FaultException<MyServiceFault> faultException)
{

}

Вот мой MyServiceFault

[DataContract]
public class MyServiceFault  
{
  [DataMember]
  public string MessageText { get; set; }

  [DataMember]
  public Guid Id { get; set; }
}

Проблема в том, что на клиенте он не переходит в блок перехвата MyServiceFault, а переходит в блок перехвата исключения связи и выдает эту ошибку

System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. ---> System.Net.WebException

Я также украсил свой метод обслуживания [FaultContract(typeof(MyServiceFault))] в интерфейсе, который реализован моим сервисом.

В моем web.config теге servicebehaviour состоит <serviceDebug includeExceptionDetailInFaults="true" />

Любая идея, где я иду не так.

Эта проблема возникает в Windows 7. Может ли быть причина, связанная с этим?

ВАЖНОЕ ОБНОВЛЕНИЕ
Согласно ответчикам, любое необработанное исключение на сервере может вызвать выброс исключения Communication на стороне клиента, и оно может не иметь никакого отношения к пользовательскому исключению сбоя, которое вы сгенерировали на сервере. Таким образом, решение состоит в том, чтобы зарегистрировать ошибки на сервере и найти, какая ошибка вызывает такое поведение. Вот очень полезная функция ведения журнала с открытым исходным кодом, которую я нашел и реализовал, которая может быть даже более полезной после того, как ваш проект перейдет в производственную среду. Большое спасибо ответчикам.

Лучший способ регистрации исключений в WCF

Ответы [ 3 ]

6 голосов
/ 26 апреля 2010

Добавьте запись в ваши вызовы WCF, включив это в ваш app.config.

<system.diagnostics>
  <trace autoflush="true" />
  <sources>
    <source name="System.ServiceModel" switchValue="Information, ActivityTracing">
      <listeners>
        <add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\LogPath\LogFile.svclog" />
      </listeners>
    </source>
  </sources>
</system.diagnostics>

(Вы можете сделать это как для сервера, так и для клиента, явно указав разные файлы журнала)

После того, как вы сгенерировали несколько журналов, просмотрите исключения или предупреждения. Я часто нахожу, что это дает некоторую очень полезную информацию, которая помогает мне решать проблемы WCF.

Чтобы прочитать файл журнала, вам нужно использовать SvcTraceViewer.exe . К сожалению, единственный способ добиться этого - использовать Windows SDK , который немного загружен для одного крошечного небольшого инструмента.

Стоит также помнить, что WCF может пройти через исключение CommunctionException, когда оно закрывается, и это ожидаемое поведение. Вы не должны просто делать using с клиентскими каналами связи WCF. Вместо этого вы должны следовать такой схеме:

try{
    x.Close()
}
catch(Comms ex){
    x.Abort()
}
4 голосов
/ 03 ноября 2011

В качестве продолжения одной из причин получения CommunicationException является то, что FaultException не может быть правильно сериализован. В журнале (см. Ответ Саймона о том, как настроить ведение журнала) это будет отображаться как «Обработка исключений», за которой следует «Ответ на операцию вызвал исключение» .

В моем случае это было вызвано не инициализацией значения перечисления:

[DataContract]
public class MyCustomWebServiceFault
{
    public MyCustomWebServiceFault()
    {
    }

    [DataMember]
    public EMyCustomWebServiceFaultReason Reason { get; set; }

    [...]

Журнал показал это:

Значение перечисления '0' недопустимо для типа 'EMyCustomWebServiceFaultReason' и не может быть сериализовано. Убедитесь, что необходимые значения перечисления присутствуют и помечены атрибутом EnumMemberAttribute, если тип имеет атрибут DataContractAttribute.

Короче говоря, используйте регистрацию или сериализацию исключений модульного теста.

4 голосов
/ 26 апреля 2010

Одна вещь, которую я узнал от работы с wcf, это то, что ошибка CommunicationException выдается много раз. Возможно даже, что ошибка, которую вы получаете, не имеет ничего общего с тем исключением, которое вы выдает, а с чем-то другим, вызывающим ее. В настоящий момент между клиентом и сервером что-то передается, трудно отследить, что вызывает исключение.

Я мог бы решить некоторые из моих проблем, изменив некоторые настройки в app.config. Установка таймаута и т.д ...

Может быть, это может помочь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...