WCF FaultException <SqlException>, перехваченный как CommunicationException - PullRequest
2 голосов
/ 06 марта 2012

У меня есть служба WCF, где я ловлю SqlException , а затем возвращаю его как FaultException, как это

throw new FaultException<SqlException>(...);

А на стороне клиента я ловлю его вот так

catch (FaultException<SqlException> e)
{
    // do something with exception
}
catch (FaultException<Exception> e)
{
    // do something with exception
}

Не думаю, что у меня есть проблема в моем web.config на стороне службы или app.config на стороне клиента (клиент winform), так как я могу перехватить FaultException<ArgumentException>, FaultException<Exception> и т. Д., Но не FaultException<SqlException>

Я не нашел ничего, что указывало бы на то, что я не могу передать SqlExceptions клиенту, мой рабочий контракт правильно настроен с такими вещами, как [FaultContract(typeof(SqlException))], и[FaultContract(typeof(Exception))]

Кто-нибудь видел это или знает наверняка, что я не могу (или, возможно, должен сделать что-то особенное для) передать ошибки типа SqlException клиенту?Спасибо.

Ответы [ 2 ]

4 голосов
/ 06 марта 2012

throw new FaultException<Exception> не совсем то, как система ошибок WCF предназначена для использования.Указанный вами тип сериализуется по проводам в элементе <Detail> ошибки SOAP.Обычно этот тип является классом контракта данных WCF, который вы пишете, например,

[DataContract]
public class MyFault {
    [DataMember]
    public string Message {get; set;}
}

throw new FaultException<Exception> работает, потому что Exception равен [Serializable], а DataContractSerializer способен обрабатывать [Serializable] типы, а также [DataContract] типы.

Однако у этого подхода есть серьезные ограничения.DataContractSerializer не очень хорошо обрабатывает типы [Serializable].Только поля примитивных типов (string, int и т. Д.) Будут передаваться корректно.Это почти нормально для очень простого типа исключения, но для сложного типа, такого как SqlException, этого недостаточно.

Мое предлагаемое решение: создайте свой собственный выделенный контракт данных для передачи данных изSqlException, что вам нужно, затем бросьте это вместо этого.Фактически, делайте это для всех типов исключений, это более безопасно и более эффективно.Я использую Enterprise Library Exception Shielding для автоматической обработки.Все, что возвращается клиенту, - это одно значение GUID, идентифицирующее данные об ошибках в журнале сервера.

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

0 голосов
/ 05 декабря 2013

Я столкнулся с этой проблемой, потому что у меня была точка останова в неправильном месте.Я удалил все точки останова с помощью Debug..Delete all Breakpoints (Ctrl-Alt-F9), и все исключения CommunicationException исчезли и были заменены правильными сообщениями, возвращающимися.

Да, время ожидания составляет 60 секунд, поэтому этого никогда не должно бытьпроизошло, так что, возможно, это был какой-то странный артефакт Visual Studio 2012.

...