Вот тут вот:
https://msdn.microsoft.com/en-us/library/ms752208(v=vs.110).aspx пишут, что сервер должен кидать FaultException<T>, а клиент соответственно — ловить FaultException<T>. А нет ли у WCF из коробки какого-то флажка, чтобы вместо FaultException можно было кидать и ловить свой тип исключений — MyVeryCustomApiException и его наследников? Понятно, что можно написать много кода и получить такое поведение, но интересует именно наличие решения из коробки. Из более-менее релевантного на той же странице нашлось "includeExceptionDetailInFaults", но оно это, конечно, не то.
Здравствуйте, andyag, Вы писали:
A>Вот тут вот: https://msdn.microsoft.com/en-us/library/ms752208(v=vs.110).aspx пишут, что сервер должен кидать FaultException<T>, а клиент соответственно — ловить FaultException<T>. А нет ли у WCF из коробки какого-то флажка, чтобы вместо FaultException можно было кидать и ловить свой тип исключений — MyVeryCustomApiException и его наследников? Понятно, что можно написать много кода и получить такое поведение, но интересует именно наличие решения из коробки. Из более-менее релевантного на той же странице нашлось "includeExceptionDetailInFaults", но оно это, конечно, не то.
На сколько я знаю нет.
А можете примерно описать, чего вам хочется добиться — может не так и много кода понадобится...
Здравствуйте, Михаил Романов, Вы писали:
МР>Здравствуйте, andyag, Вы писали:
A>>Вот тут вот: https://msdn.microsoft.com/en-us/library/ms752208(v=vs.110).aspx пишут, что сервер должен кидать FaultException<T>, а клиент соответственно — ловить FaultException<T>. А нет ли у WCF из коробки какого-то флажка, чтобы вместо FaultException можно было кидать и ловить свой тип исключений — MyVeryCustomApiException и его наследников? Понятно, что можно написать много кода и получить такое поведение, но интересует именно наличие решения из коробки. Из более-менее релевантного на той же странице нашлось "includeExceptionDetailInFaults", но оно это, конечно, не то.
МР>На сколько я знаю нет.
МР>А можете примерно описать, чего вам хочется добиться — может не так и много кода понадобится...
[ServiceContract]
interface ICalculator
{
[OperationContract]
[SuperMegaFaultContract(DivisionByZeroException)] // <-----------
int Divide(int a, int b);
}
class ApiException : Exception {}
class DivisionByZeroException : ApiException {}
class Calculator : ICalculator
{
public int Divide(int a, int b)
{
throw new DivisionByZeroException(); // <----------- вот тут кидается
}
}
...
var calculator = channelFactory.GiveMe(typeof(ICalculator));
try
{
calculator.Divide(1, 0); // <--------- летит вот отсюда
Assert.Fail()
}
catch(DivisionByZeroException e) // <-----------
{
// ожидается, что попадём сюда
}
Как-то так.
Здравствуйте, andyag, Вы писали:
A>Как-то так.
Ну нечто подобное я и предполагал... Логично
В общем, "из коробки" такое работать действительно не будет.
Причем, основная проблема мне видится в том, что Exception, после раскрутки стека (т.е. когда его ловит инфраструктура WCF) не сериализуется стандартным WCF сериализатором.
В принципе, не так и сложно сделать некоторую доработку, чтобы получить желаемое вами поведение:
Добавить глобальный IErrorHandler — для перекладывания всех исключений (или тех, которые вы решите отправлять на клиента) в fault сообщение
На клиенте принять такое сообщение, достать исключение, восстановить и перевыбросить.
Вот
тут есть на первый взгляд вполне готовое решение, но, увы непроверенное.
Там для прокидывания используется NetDataContractSerializer (значит нужно будет для контрактов использовать shared-сборки), а на клиенте MessageInspector, который вычитывает детальную информацию из фолта и выбрасывает исключение. Все остальное там — behaviors, для добавления этих расширений.
У автора сделано для всех исключений вообще, но вы можете ограничиться только своей иерархией.
Сам я так не делал никогда, в первую очередь из-за необходимости "доработки" клиента, поэтому оценить решение не возьмусь. Но выглядит логично (по крайней мере я бы делал аналогично, будь такая задача нужна). Единственный вопрос в том как выбрасывать исключение на клиенте, чтобы не потерять информацию из исключения на сервере. Но тут я бы поступил примерно так:
Во все передаваемые на клиента исключения добавил некий CorrelationID (ErrorID), который заполнялся бы в момент генерации исключения
На сервере в том же обработчике записывал бы исключение в логи (явно выделяя ID, по которому потом нужно будет сопоставлять).
На клиенте выбрасывал бы заново, не обращая внимания, на то, что теряется тот же стек — главное, чтобы уцелело ID. Ну а потом бы уже сопоставлял ошибки на сервере и клиенте.
P.S. Да, на решение "из коробки" не тянет. Но, мне кажется из коробки такое вряд ли кто-то взялся бы делать.
Здравствуйте, andyag, Вы писали:
A>Вот тут вот: https://msdn.microsoft.com/en-us/library/ms752208(v=vs.110).aspx пишут, что сервер должен кидать FaultException<T>, а клиент соответственно — ловить FaultException<T>. А нет ли у WCF из коробки какого-то флажка, чтобы вместо FaultException можно было кидать и ловить свой тип исключений — MyVeryCustomApiException и его наследников? Понятно, что можно написать много кода и получить такое поведение, но интересует именно наличие решения из коробки. Из более-менее релевантного на той же странице нашлось "includeExceptionDetailInFaults", но оно это, конечно, не то.
Шибко много кода писать не надо.
вам надо реализовать IErrorHandler и привязать его к серверу + реализовать IClientMessageInspector на предмет анализа приходящих ошибок клиенту от севера. Инспектор нужно в свою очередь прикрутить к клиенту.
Здравствуйте, andyag, Вы писали:
A>Вот тут вот: https://msdn.microsoft.com/en-us/library/ms752208(v=vs.110).aspx пишут, что сервер должен кидать FaultException<T>, а клиент соответственно — ловить FaultException<T>. А нет ли у WCF из коробки какого-то флажка, чтобы вместо FaultException можно было кидать и ловить свой тип исключений — MyVeryCustomApiException и его наследников? Понятно, что можно написать много кода и получить такое поведение, но интересует именно наличие решения из коробки. Из более-менее релевантного на той же странице нашлось "includeExceptionDetailInFaults", но оно это, конечно, не то.
А можете сказать — для чего это надо? Есть стандартное FaultException, в него можно включить все, что угодно. Если делать то, что хотите вы, то другой стороне, реализовывать которую могут другие люди (или поддерживать) придется закладываться на такое нестандартное поведение. Зачем?