Поделиться через


Сбои при отправке и получении

Ошибки SOAP передают сведения об ошибке от службы клиенту и, в дуплексном случае, от клиента службе совместимым способом. Как правило, служба определяет пользовательское содержимое ошибки и указывает операции, которые могут возвращать такие ошибки. (Дополнительные сведения см. в разделе Определение и задание сбоев.) В этом разделе описывается, как служба или дуплексный клиент могут отправлять такие ошибки в случае возникновения соответствующих условий и как клиентское приложение или приложение службы обрабатывает эти ошибки. Общие сведения об обработке ошибок в приложениях Windows Communication Foundation (WCF) см. в разделе Задание и обработка сбоев в контрактах и службах.

Отправка ошибок SOAP

Объявленные ошибки SOAP — это ошибки, в которых в операции имеется атрибут System.ServiceModel.FaultContractAttribute, указывающий пользовательский тип ошибки SOAP. Необъявленные ошибки SOAP — это ошибки, не указанные в контракте операции.

Отправка объявленных ошибок

Чтобы отправить объявленную ошибку SOAP, необходимо обнаружить условия ошибки, в которых возникает ошибка SOAP, и создать новое исключение System.ServiceModel.FaultException, в котором параметр типа является новым объектом типа, указанным в атрибуте FaultContractAttribute для этой операции. В следующем примере кода показано, как с помощью атрибута FaultContractAttribute указать, что операция SampleMethod может возвращать ошибку SOAP с типом по умолчанию GreetingFault.

<OperationContract, FaultContractAttribute(GetType(GreetingFault), Action:="https://www.contoso.com/GreetingFault", ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Function SampleMethod(ByVal msg As String) As String

Для передачи клиенту сведений об ошибке GreetingFault необходимо перехватить ошибку и создать новое исключение System.ServiceModel.FaultException типа GreetingFault с новым объектом GreetingFault в качестве аргумента; см. пример кода ниже. Если клиент является клиентским приложением WCF, исключение обрабатывается как управляемое исключение, принадлежащее типу System.ServiceModel.FaultException типа GreetingFault.

  Throw New FaultException(Of GreetingFault)(New GreetingFault("A Greeting error occurred. You said: " & msg))
End If

Отправка необъявленных ошибок

Отправка необъявленных ошибок может оказаться очень полезной для быстрой диагностики и отладки ошибок в приложениях WCF, однако ее возможности в качестве средства отладки ограничены. В общем случае при отладке рекомендуется использовать свойство System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults. Если свойству присвоено значение true, клиенты получают такие ошибки в виде исключений FaultException типа ExceptionDetail.

ms732013.Important(ru-ru,VS.100).gif Примечание
Управляемые исключения могут предоставлять внутренние сведения о приложении, поэтому присвоение свойству System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults или System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults значения true позволяет клиентам WCF получать информацию о внутренних исключениях операции службы.

Поэтому задавать для свойства System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults или System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults значение true рекомендуется только для временной отладки приложения службы. Кроме того, WSDL для метода, который возвращает такие необработанные управляемые исключения, не содержит контракт для исключения FaultException типа ExceptionDetail. В клиентах должна быть предусмотрена возможность получения неизвестной ошибки SOAP (возвращаемой клиентам WCF в виде объектов System.ServiceModel.FaultException) для надлежащего получения отладочной информации.

Чтобы отправить необъявленную ошибку SOAP, необходимо создать объект System.ServiceModel.FaultException (не универсального типа FaultException) и передать строку конструктору. Она предоставляется клиентскому приложению WCF в виде исключения System.ServiceModel.FaultException. Доступ к строке в этом исключении можно получить с помощью метода System.ServiceModel.FaultException.ToString.

ms732013.note(ru-ru,VS.100).gifПримечание
Если объявлена ошибка SOAP строкового типа, а затем она выдана службе в виде объекта FaultException с параметром типа System.String, значение строки присваивается свойству System.ServiceModel.FaultException.Detail и недоступно в свойстве System.ServiceModel.FaultException.ToString.

Обработка ошибок

В клиентах WCF ошибки SOAP, возникающие при передаче данных и относящиеся к клиентским приложениям, выдаются в виде управляемых исключений. Во время выполнения любой программы возникает множество исключений, однако можно ожидать, что в результате передачи данных приложения, использующие модель программирования клиента WCF, будут обрабатывать исключения двух следующих типов.

Объекты TimeoutException выдаются по истечении заданного времени ожидания.

Объекты CommunicationException выдаются в случае возникновения устранимой ошибки передачи данных в службе или клиенте.

Класс CommunicationException имеет два важных производных типа, FaultException и универсальный тип FaultException.

Исключения FaultException выдаются, когда прослушиватель получает неожиданную или не указанную в контракте операции ошибку. Обычно это происходит во время отладки приложения, когда свойству System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults службы присвоено значение true.

Исключения FaultException выдаются в клиенте при получении ошибки, указанной в контракте операции, в ответ на двустороннюю операцию (т.е. метод с атрибутом OperationContractAttribute, у которого свойству IsOneWay присвоено значение false).

ms732013.note(ru-ru,VS.100).gifПримечание
Когда служба WCF имеет свойство System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults или System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults со значением true, клиент получает необъявленное исключение FaultException, принадлежащее типу ExceptionDetail. Клиенты могут либо перехватить эту определенную ошибку, либо обработать ее в блоке catch для FaultException.

Как правило, только исключения FaultException, TimeoutException и CommunicationException представляют интерес для клиентов и служб.

ms732013.note(ru-ru,VS.100).gifПримечание
Конечно, возникают и другие исключения. К неожиданным исключениям относятся неустранимые ошибки, например System.OutOfMemoryException. Как правило, приложения не должны перехватывать такие методы.

Перехват исключений ошибок в правильном порядке

Поскольку класс FaultException является производным класса FaultException, а класс FaultException является производным класса CommunicationException, важно перехватывать эти исключения в нужном порядке. Например, если в блоке try/catch сначала перехватывается исключение CommunicationException, обработка всех объявленных и необъявленных ошибок SOAP будет выполняться в этом блоке. Все последующие блоки catch, предназначенные для обработки пользовательского исключения FaultException, не вызываются никогда.

Помните, что одна операция может возвращать любое количество объявленных ошибок. Каждая ошибка имеет уникальный тип и должна обрабатываться отдельно.

Обработка исключений при закрытии канала

Большая часть вышесказанного касалась ошибок, отправляемых в процессе обработки сообщений приложения, т.е. сообщений, явно отправляемых клиентом, когда клиентское приложение вызывает операции с объектом клиента WCF.

Даже при удалении локального объекта могут быть созданы или скрыты исключения, возникающие в процессе перезапуска. Аналогичная ситуация может иногда возникать при работе с объектами клиента WCF. При вызове операций сообщения передаются по установленному подключению. Закрытие канала может приводить к исключениям, если не удается аккуратно закрыть подключение или если оно уже закрыто, даже при надлежащем возврате всех операций.

Как правило, каналы объекта клиента закрываются одним из следующих способов.

  • При перезапуске объекта клиента WCF.

  • При вызове метода System.ServiceModel.ClientBase.Close клиентским приложением.

  • При вызове метода System.ServiceModel.ICommunicationObject.Close клиентским приложением.

  • При вызове клиентским приложением операции, которая является завершающей операцией сеанса.

Во всех случаях при закрытии канал получает указания начать закрытие всех базовых каналов, которые могут отправлять сообщения для поддержки сложных функций на уровне приложения. Например, если контракту требуются сеансы, привязка предпринимает попытки установить сеанс путем обмена сообщениями с каналом службы до тех пор, пока сеанс не будет установлен. После закрытия канала базовый канал сеанса уведомляет службу о прерывании сеанса. Если канал уже был прерван, закрыт или иным образом стал непригодным (например, при отключении сетевого кабеля), канал клиента не может уведомить канал службы о прекращении сеанса и возможном исключении.

Прерывание работы канала при необходимости

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

Если ошибка содержит сведения об ошибке, касающиеся операции, и существует возможность использования ее другими объектами, прерывать канал не требуется (такие случаи являются редкими). Во всех остальных случаях рекомендуется прерывать канал. Пример, демонстрирующий все эти моменты, см. в разделе Ожидаемые исключения.

В следующем примере кода демонстрируется обработка исключений ошибок SOAP в простом клиентском приложении, в том числе объявленных и необъявленных ошибок.

ms732013.note(ru-ru,VS.100).gifПримечание
В этом примере кода не используется конструкция using. При закрытии каналов могут создаваться исключения, поэтому рекомендуется в приложениях сначала создать клиент WCF, а затем открыть, использовать и закрыть клиент WCF в одном блоке try. Дополнительные сведения см. в разделах Общие сведения о клиентах WCF и Предотвращение проблем при использовании операторов.

Imports System
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
  Public Shared Sub Main()
    ' Picks up configuration from the config file.
    Dim wcfClient As New SampleServiceClient()
    Try
      ' Making calls.
      Console.WriteLine("Enter the greeting to send: ")
      Dim greeting As String = Console.ReadLine()
      Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

      Console.WriteLine("Press ENTER to exit:")
      Console.ReadLine()

      ' Done with service. 
      wcfClient.Close()
      Console.WriteLine("Done!")
    Catch timeProblem As TimeoutException
      Console.WriteLine("The service operation timed out. " & timeProblem.Message)
      Console.ReadLine()
      wcfClient.Abort()
    Catch greetingFault As FaultException(Of GreetingFault)
      Console.WriteLine(greetingFault.Detail.Message)
      Console.ReadLine()
      wcfClient.Abort()
    Catch unknownFault As FaultException
      Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
      Console.ReadLine()
      wcfClient.Abort()
    Catch commProblem As CommunicationException
      Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
      Console.ReadLine()
      wcfClient.Abort()
    End Try
  End Sub
End Class

См. также

Задачи

Ожидаемые исключения
Предотвращение проблем при использовании операторов

Справочник

FaultException
FaultException
System.ServiceModel.CommunicationException