'

WCF-службы Обработка ошибок

Понравилась презентация – покажи это...





Слайд 0

ДонНУ, кафедра КТ, проф.В.К.Толстых Из цикла лекций «Internet-технологии разработки приложений» для студентов 4-го курса кафедры Компьютерных технологий физического факультета Донецкого национального университета проф. В. К. Толстых WCF-службы Обработка ошибок Централизованная (расширенная) обработка ошибок Передача нестандартных деталей в исключении Исключение FaultException


Слайд 1

Концепция обработки ошибок Если в сервисе происходит исключение, то клиенту не обязательно знать обо всех тонкостях этого исключения, ему важен факт ошибки и основная причина ее возникновения. Все тонкости важны только на этапе отладки. Исключения, возникающие в WCF-сервисе, не нарушают работу хостового процесса, а также работу других запущенных сервисов и клиентов, не имеющих отношения к этим исключениям. Когда необработанное исключение выходит из области видимости сервиса, диспетчер канала перехватывает и обрабатывает его, возвращая в сериализованном виде в SOAP-сообщении клиенту. Когда сообщение попадает к посреднику (к прокси клиента), последний инициирует исключение на стороне клиента. Ex0 – первоначальное исключение, возникшее в сервисе, Ex1 – исключение, предназначенное для передачи клиентской стороне.


Слайд 2

Ошибки, получаемые клиентом сервиса При обращении к сервису, клиент может столкнуться с тремя типами ошибок: Коммуникационные ошибки. Возникают, например, когда нет подключения к сети, когда указан неправильный адрес сервиса, когда не запущен host-процесс и т.д. Эти исключения определены на клиентской стороне классом исключения CommunicationException. Ошибки состояния канала. Связаны с состоянием каналов и прокси клиента. Такой ошибкой может быть, например, попытка доступа к уже закрытому прокси, которая оканчивается исключением класса ObjectDisposedException, или, например, несоответствие между контрактом и уровнем безопасности привязки. Ошибки запросов. Происходят при работе сервисов. Возникающие исключения CLR не передаются за пределы сервисов, они преобразуются в сбои (faults) – нейтральная информация для клиентов. Для возврата клиенту в SOAP-сообщении сбои сервисов сериализуются.


Слайд 3

Исключение FaultException возникает когда прокси клиента получает не типизированную (не указанную в контракте операции) ошибку в SOAP. Оно должно перехватываться до обработки CommunicationException. Не типизированные ошибки отправляются клиенту при соответствующей настройке отладки поведения службы в файле конфигурации (см. далее). Иерархия наследования от System.ServiceModel.CommunicationException в клиентах сервисов         ActionNotSupportedException         AddressAccessDeniedException         AddressAlreadyInUseException         Channels.RedirectionException         Channels.RetryException         ChannelTerminatedException         CommunicationObjectAbortedException         CommunicationObjectFaultedException         Dispatcher.MessageFilterException         EndpointNotFoundException   FaultException         Persistence.PersistenceException         PoisonMessageException         ProtocolException         Security.MessageSecurityException         Security.SecurityAccessDeniedException         SSecurity.SecurityNegotiationException         ServerTooBusyException         ServiceActivationException


Слайд 4

Исключения и экземпляры службы Воздействие, оказываемое исключениями на клиента и на экземпляр службы, зависит от режима управления экземплярами. Службы уровня вызова: Экземпляр службы уничтожается, посредник инициирует исключение FaultException на стороне клиента, канал связи закрывается. Даже если клиент перехватит исключение, то последующие вызовы приведут к CommunicationObjectFaulted-Exception. Клиент только может закрыть посредника. Сеансовые службы: - аналогично службам уровня вызова, сеанс завершается. Синглетные службы: Экземпляр службы не уничтожается и продолжает работать, канал связи закрывается, клиент только может закрыть посредника. Прокси клиента, при получении сериализованных ошибок запроса, десериализует их и генерирует иерархические исключения классов: FaultException<TDetail>, FaultException и CommunicationException. Ошибки запросов принимаются клиентом при двухстороннем взаимодействии т.е. при [OperationContract(IsOneWay = false)] соответствующего метода. Для односторонней привязки WSHttpBinding , если не задано явно IsOneWay=true, то автоматически организуется второй HTTP-канал.


Слайд 5

Контракты сбоев При помощи контрактов сбоев служба перечисляет типы ошибок которые она может инициировать. WCF-клиент по контракту сбоев отличает контрактные ошибки от других. Атрибут FaultContract применяется непосредственно к контрактным операциям, и в нём указывается тип детализации ошибки, например: [ServiceContract] public interface IServiceName { [OperationContract(IsOneWay = false)] [FaultContract(typeof(FaultException))] string GetData(int value); [OperationContract(IsOneWay = false)] [FaultContract(typeof(DivideByZeroException))] int DivideInt(int n1, int n2); } Исключения в методах служб должны использовать точно такой же тип как указано в контракте сбоев. Для данного примера метод DivideInt() должен инициировать исключение FaultException<DivideByZeroException>. Не забывайте после изменения методов и контрактов настраивать посредника у клиента, т.е. в Visual Studio – удалить и заново создать ссылку на WCF-службу.


Слайд 6

Настройка поведения службы для FaultException <behaviors> <serviceBehaviors> <behavior name="MyBehavior"> <serviceMetadata httpGetEnabled="true"/> <!-- Передавать клиенту исключения --> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> Для передачи исключений типа FaultException клиенту необходимо в поведении службы настроить следующий отладочный режим: Не типизированные ошибки службы (клиентские исключения типа FaultException) возвращают объект-строку, которая не требуют сериализации. Клиент получает информацию об ошибке сервиса в свойстве Message исключения FaultException. Обычно, этих средств достаточно для отладки сервиса и нет необходимости создавать и организовывать сериализацию специализированного объекта типа TDetail.


Слайд 7

Пример клиента SampleServiceClient wcfClient = new SampleServiceClient(); try { // Вызов сервиса… } catch (TimeoutException timeProblem){ Console.WriteLine("Timed out " + timeProblem.Message); wcfClient.Close(); Console.ReadLine(); } // Перехватить неизвестное исключение типа FaultException catch (FaultException faultEx){ Console.WriteLine(" Неизвестное исключение "+faultEx.Message+faultEx.StackTrace); Console.Read(); wcfClient.Close(); } // Перехватить стандартное исключение типа CommunicationException catch (CommunicationException commProblem){ Console.WriteLine("Ошибка подключения " + commProblem.Message + commProblem.StackTrace); Console.Read(); wcfClient.Close(); }


Слайд 8

Пример 1 службы Контракт службы: Проект службы: Помещаем службу в пространство имён WcfTest Генерируем исключение Метод службы Создаём для SOAP службы непредвиденные сбои метода GetData()


Слайд 9

Конфигурация службы Дополнительные (нестандартные) настройки привязки Служба ServiceName в пространстве имён WcfTest Рабочая конечная точка службы Идентичность рабочей точки Передавать клиенту подробности ошибки, возникающие в службе ServiceName В случае false клиент получит сообщение: Серверу не удалось обработать запрос из-за внутренней ошибки.


Слайд 10

Клиент для примера службы


Слайд 11

Код клиента Не используйте оператор using(ServiceRef.ServiceNameClient proxy = ...) для создания proxy при возврате ошибок, канал посредника будет закрыт раньше времени. Никогда не используйте экземпляр посредника после исключения, даже если оно было перехвачено.


Слайд 12

Пример 2 службы Метод службы: Контракт службы: Клиент службы: Не забудьте заранее компилировать службу.


Слайд 13

Передача нестандартных деталей в исключении Через исключение FaultException можно вернуть клиенту любой объект с деталями сбоя. Например, вы сохраняете детали сбоя посредством объекта Data типа IDictionary, представляющего собой массив пар key/value: exception.Data.Add("code", "205"); exception.Data.Add("message", "Внутренняя ошибка"); В нужном месте WCF необходимо сгенерировано исключение FaultException с передачей объекта типа IDictionary: throw new FaultException<System.Collections.IDictionary>(exception.Data); Контракт сбоев данной операции при этом должен иметь атрибут того же типа: [FaultContract(typeof(System.Collections.IDictionary))] Теперь клиент может получить детали исключения посредством: catch (FaultException<System.Collections. Generic.Dictionary<object,object>> e) { Label1.Text = e.Detail["code"]; }


Слайд 14

Расширение обработки ошибок public class MyErrorHandler: IErrorHandler { void ProvideFault( Exception error, MessageVersion version, ref Message fault); bool HandleError(Exception error); } Этот обработчик связывается с диспетчером канала, после чего появляется возможность перехватывать и обрабатывать все исключения, которые возникают в сервисе. WCF позволяет разработчикам не только настраивать заданную по умолчанию обработку исключений, но и определять собственные обработчики в различных точках расширения функциональности WCF во время выполнения. Для создания собственного обработчика ошибок необходимо реализовать интерфейс IErrorHandler:


Слайд 15

Методы ProvideFault и HandleError Метод ProvideFault() вызывается сразу после того, как происходит исключение. Если реализация метода будет «пустой», то входное исключение не будет изменено. Для предоставления альтернативного исключения необходимо создать собственное сообщение об ошибке, которая и будет передана клиенту. Суть метода заключается в преобразовании входного исключения в некоторую альтернативную форму, которая распространится дальше до клиента. Метод HandleError() вызывается после передачи управления клиенту и выпол-няется в отдельном потоке, нежели клиентский запрос и преобразование исключений ProvideFault(). В связи с этим, обработка ошибок может осуществляться даже после передачи управления клиенту, поэтому время её выполнения не столь критично. Метод HandleError() не оказывает никакого воздействия на клиентское приложение . Это удобный способ централизованного ведения лога ошибок сервиса.


Слайд 16

Пример реализации обработчиков ошибок public class MyErrorHandler : IErrorHandler { bool HandleError(Exception error) { try { MyServiceLogging.Log(error); } catch { } // не останавливать вызов расширенной обработки исключений: finally { return false; } } public void ProvideFault( Exception error, MessageVersion version, ref Message fault) { // Пример – анализ входного исключения – деление на ноль: if (error is DivideByZeroException) { // формирование сообщения с исключением для клиента (детали не включаем) FaultException<DivideByZeroException> faultException = new FaultException<DivideByZeroException>(null, error.Message); MessageFault messageFault = faultException.CreateMessageFault(); fault = Message.CreateMessage(version, messageFault, faultException.Action); } ... } }


Слайд 17

Установка расширенной обработки ошибок Диспетчер канала WCF имеет коллекцию обработчиков ошибок Collection<IErrorHandler>. Чтобы установить собственную реализацию интерфейса IErrorHandler, требуется лишь добавить ее в эту коллекцию. Для этого в реализации сервиса должен быть использован атрибут ErrorHandlerBehavior : [ErrorHandlerBehavior(typeof(MyErrorHandler))] public class MyService : IMyContract { ... } Код реализации данного атрибута необходимо добавить в класс сервиса. Исходный код можно взять, например, в статье http://www.rsdn.ru/article/dotnet/FaultsWCF.xml


Слайд 18

Источники Джувел Лёве. Создание служб Windows Communication Foundation. – СПб.: Питер, 2008 . – 592 с.: ил. http://msdn.microsoft.com http://www.rsdn.ru/article/dotnet/FaultsWCF.xml


×

HTML:





Ссылка: