Обзор. В этом разделе в основном описываются исключения и смоделированные исключения, которые могут возникнуть при вызовах служб, а также анализируется, когда и какие исключения могут быть перехвачены, а также как правильно передавать исключения службы клиенту.
В конце статьи приведена последовательность правильного перехвата исключений. Этот захват исключений является лишь введением, и некоторые из него представляют собой функции приложения, поэтому код и его написание относительно просты. Он также знакомит с некоторыми методами обработки исключений на стороне сервера.
1. Сначала мы создаем простой сервер и клиент калькулятора следующим образом:
Нажмите, чтобы развернуть код
//Сервер[ServiceContract]публичный интерфейс ICalc{[OperationContract][FaultContract(typeof(GreentingError))]string Div(int x, int y);}public class Calc: ServiceBase, ICalc {public string Div(int x, int y); ) ) {string result = string.Empty; try {result = string.Format("result: {0}", x / y); } catch (DivideByZeroException ex) {throw ex; } return result }}//Client [ServiceContract] общедоступный интерфейс ICalc {[OperationContract] [FaultContract(typeof(GreentingError))] string Div(int x, int y } public class CalcClient: ClientBase<ICalc>, ICalc{public string Div(int x, int y); ) ) {return base.Channel.Div(x, y }});
Ладно, признаю, что код довольно простой, но я люблю простые вещи.
2. Простые вещи — это хорошо, и называть их гораздо проще.
попробуйте { CalcClientcalcclient = новый результат строки Calcclient.Div(10, 0); Console.WriteLine(result); Console.ReadKey(); } catch (TimeoutExceptionex) {throw ex; ex) {throw ex; } catch (FaultExceptionex) {throw ex;
3. Когда мы вызываем метод службы Div(int x, int y) и передаем значение 0 в логарифм y, сервер выдаст ожидаемое исключение DivideByZeroException. В это время,
Это исключение перехватывается в разделе FaultException клиента.
4. Нет проблем, мы вручную создадим FaultException в коде сервера.
catch (DivideByZeroException ex) {Исключение FaultException = новое исключение FaultException (ex.Message);}
В это время я обнаружил, что FaultException перехватил это исключение. Почему?
5. Проведите еще один тест.
Добавьте в службу этот код: System.Threading.Thread.Sleep(70000), чтобы время ожидания службы истекло.
На этот раз TimeOutException наконец перехватил исключение сервера, поэтому мы должны спросить, когда FaultException<GreentingError> перехватит это исключение? Ответ заключается в том, что когда сервер выдает FaultException<GreentingError>, процитируйте отрывок из MSDN (зеленая часть):
Если прослушиватель получает ошибку SOAP, которая не ожидается или не указана в контракте операции, будет создан объект FaultException. Могут быть отправлены два типа ошибок SOAP: объявленные и необъявленные. Объявленная ошибка SOAP — это ошибка, в которой операция имеет атрибут System.ServiceModel.FaultContractAttribute, указывающий настраиваемый тип ошибки SOAP. Необъявленные ошибки SOAP — это ошибки, которые не указаны в контракте операции. «Неожиданная или неуказанная ошибка SOAP» здесь относится к пользовательскому типу ошибки, который не заключен в FaultContractAttribute в операции службы.
6. Когда же будет перехвачено исключение CommincationException?
MSDN сообщает: приложение обрабатывает объекты CommunicationException, которые могут быть выброшены во время связи.
Что ж, чтобы вызвать это исключение, мы делаем следующее. Сначала закройте текущий объект канала на сервере.
OperationContext.Current.Channel.Close();
К сожалению, клиент не перехватил CommunicationException, но поймал TimeOutException! Поскольку после закрытия канала обслуживания никаких исключений не произошло, клиенту не было возвращено сообщение. После ожидания в течение определенного периода времени клиент вышел из строя.
Поэтому мы указываем TimeSpan при закрытии канала. Это позволяет немедленно выполнить возврат вызова. Конечно, возврат вызова также можно выполнить с помощью Channel.Abort.
OperationContext.Current.Channel.Close(новый TimeSpan(5000));
При вызове метода Close IContextChannel укажите время, когда операция отправки должна быть завершена до истечения времени ожидания, чтобы сообщение можно было вернуть немедленно в течение указанного времени, не дожидаясь истечения времени ожидания вызова службы, иначе клиент обязательно выдаст ошибку. исключение TimeOutException вместо исключения CommunicationException.
7. Средства правовой защиты
В то же время, чтобы принять некоторые меры по исправлению ситуации в случае возникновения исключения в службе, мы создали новый абстрактный класс ServiceBase и наследовали от него класс реализации службы Calc, чтобы мы могли получить контроль над различными переходами состояний сервис. Класс ServiceBase выглядит следующим образом:
общедоступный абстрактный частичный класс ServiceBase { частный канал IContextChannel = null; protected ServiceBase() {channel = OperationContext.Current.Channel; ; Channel.Opened += new EventHandler(delegate(object sender, EventArgs e) {/* TO DO*/ }); Channel.Closing += new EventHandler(delegate(object sender, EventArgs e) {/* TO DO*/ }); Channel.Closed += new EventHandler(delegate(object sender, EventArgs e) { Abort(); }); Channel.Faulted += new EventHandler(delegate(object sender, EventArgs e) { Abort(); }) } void Open() {/* TO DO*/ } void Close() { /* TO DO*/} void Abort() {channel.Abort() }};
Как видно из приведенного выше кода, после закрытия канала службы мы немедленно останавливаем службу и позволяем сообщению немедленно вернуться. В это время, даже если служба закрыта во время операции без указания времени завершения таймаута, вызов. все еще может вернуться немедленно.
На этот раз клиент наконец поймал CommunicationException, как показано на рисунке ниже:
Почему это происходит?
8. Давайте посмотрим на иерархию наследования CommunicationException, из которой мы можем черпать вдохновение.
8.1. Первый — это иерархия наследования FaultException<TDetail>.
8.2, снова иерархия наследования TimeOutException.
9. Как видно из приведенного выше рисунка, TimeOutException и CommunicationException наследуются от класса SystemException, тогда как FaultException наследуется от CommunicationException и, наконец, FaultException<TDetail> наследуется от класса FaultException.
10. Наконец, мы пришли к выводу, что правильный порядок перехвата исключений на клиенте должен быть таким:
TimeOutException> FaultException<TDetail> > FaultException > CommunicationException > Exception. Настоятельно рекомендуется разработчикам создавать и перехватывать исключения типа FaultException<TDetail>.
Автор: Лао Ми Источник: http://www.cnblogs.com/viter/
Авторские права на эту статью принадлежат автору и Blog Park. Перепечатка приветствуется. Однако данное заявление должно быть сохранено без согласия автора, а ссылка на оригинальный текст должна быть предоставлена на видном месте на странице статьи. право на юридическую ответственность сохраняется.