Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
As falhas SOAP transmitem informações de condição de erro de um serviço para um cliente e, no caso duplex, de um cliente para um serviço de maneira interoperável. Normalmente, um serviço define o conteúdo de falha personalizado e especifica quais operações podem devolvê-los. (Para obter mais informações, consulte Definindo e especificando falhas.) Este tópico discute como um cliente de serviço ou duplex pode enviar essas falhas quando a condição de erro correspondente ocorreu e como um cliente ou aplicativo de serviço lida com essas falhas. Para obter uma visão geral do tratamento de erros em aplicativos do WCF (Windows Communication Foundation), consulte Especificando e tratando falhas em contratos e serviços.
Envio de falhas de SOAP
Falhas SOAP declaradas são aquelas em que uma operação possui um System.ServiceModel.FaultContractAttribute que especifica um tipo personalizado de falha SOAP. Falhas SOAP não declaradas são aquelas que não são especificadas no contrato para uma operação.
Envio de falhas declaradas
Para enviar uma falha SOAP declarada, detecte a condição de erro para a qual a falha SOAP é apropriada e gere um novo System.ServiceModel.FaultException<TDetail>, onde o parâmetro de tipo é um novo objeto do tipo especificado no FaultContractAttribute para essa operação. O exemplo de código a seguir mostra o uso de FaultContractAttribute para especificar que a operação SampleMethod pode retornar uma falha SOAP com o tipo de detalhe de GreetingFault.
[OperationContract]
[FaultContractAttribute(
typeof(GreetingFault),
Action="http://www.contoso.com/GreetingFault",
ProtectionLevel=ProtectionLevel.EncryptAndSign
)]
string SampleMethod(string msg);
<OperationContract, FaultContractAttribute(GetType(GreetingFault), Action:="http://www.contoso.com/GreetingFault", ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Function SampleMethod(ByVal msg As String) As String
Para transmitir as informações de erro de GreetingFault para o cliente, pegue a condição de erro apropriada e lance um novo System.ServiceModel.FaultException<TDetail> do tipo GreetingFault com um novo objeto GreetingFault como o argumento, como no exemplo de código a seguir. Se o cliente for um aplicativo cliente WCF, ele experimenta isso como uma exceção gerenciada em que o tipo é System.ServiceModel.FaultException<TDetail> do tipo GreetingFault.
throw new FaultException<GreetingFault>(new GreetingFault("A Greeting error occurred. You said: " + msg));
Throw New FaultException(Of GreetingFault)(New GreetingFault("A Greeting error occurred. You said: " & msg))
End If
Envio de falhas não declaradas
O envio de falhas não declaradas pode ser muito útil para diagnosticar e depurar problemas rapidamente em aplicativos WCF, mas sua utilidade como ferramenta de depuração é limitada. Em geral, ao depurar, é recomendável que você use a propriedade ServiceDebugBehavior.IncludeExceptionDetailInFaults. Quando você define esse valor como true, os clientes experimentam falhas como FaultException<TDetail> exceções do tipo ExceptionDetail.
Importante
Como as exceções gerenciadas podem expor informações internas do aplicativo, definir ServiceBehaviorAttribute.IncludeExceptionDetailInFaults ou ServiceDebugBehavior.IncludeExceptionDetailInFaults pode permitir que clientes do WCF obtenham informações sobre exceções internas de operação de serviço, incluindo informações pessoalmente identificáveis ou outras informações confidenciais.
Portanto, definir ServiceBehaviorAttribute.IncludeExceptionDetailInFaults ou ServiceDebugBehavior.IncludeExceptionDetailInFaults como true é recomendado apenas para depuração temporária de um aplicativo de serviço. Além disso, o WSDL para um método que retorna exceções gerenciadas não tratadas dessa forma não contém o contrato do FaultException<TDetail> tipo ExceptionDetail. Os clientes devem esperar a possibilidade de uma falha SOAP desconhecida (retornada aos clientes do WCF como objetos System.ServiceModel.FaultException) para obter as informações de depuração corretamente.
Para enviar uma falha SOAP não declarada, jogue um System.ServiceModel.FaultException objeto (ou seja, não o tipo FaultException<TDetail>genérico) e passe a cadeia de caracteres para o construtor. Isso é exposto aos aplicativos cliente do WCF como uma exceção gerada System.ServiceModel.FaultException, em que a cadeia de caracteres está disponível chamando o método FaultException<TDetail>.ToString.
Observação
Se você declarar uma falha de SOAP da cadeia de caracteres de tipo e, em seguida, lançar isso em seu serviço como um FaultException<TDetail>, em que o parâmetro de tipo é um System.String, o valor da cadeia de caracteres será atribuído à propriedade FaultException<TDetail>.Detail e não estará disponível em FaultException<TDetail>.ToString.
Tratamento de falhas
Em clientes WCF, falhas SOAP que ocorrem durante a comunicação que são de interesse para aplicativos cliente são geradas como exceções gerenciadas. Embora haja muitas exceções que podem ocorrer durante a execução de qualquer programa, os aplicativos que usam o modelo de programação do cliente WCF podem esperar lidar com exceções dos dois tipos a seguir como resultado da comunicação.
TimeoutException objetos são lançados quando uma operação excede o período de tempo limite especificado.
Objetos CommunicationException são gerados quando há alguma condição de erro de comunicação recuperável no serviço ou no cliente.
A CommunicationException classe tem dois tipos derivados importantes FaultException e o tipo genérico FaultException<TDetail> .
FaultException as exceções são geradas quando um ouvinte recebe uma falha que não é esperada ou especificada no contrato de operação; geralmente isso ocorre quando o aplicativo está sendo depurado e o serviço tem a ServiceDebugBehavior.IncludeExceptionDetailInFaults propriedade definida como true.
As exceções FaultException<TDetail> são geradas no cliente quando uma falha especificada no contrato de operação é recebida em resposta a uma operação bidirecional (ou seja, um método com um atributo OperationContractAttribute, com IsOneWay definido como false).
Observação
Quando um serviço WCF tem a propriedade ServiceBehaviorAttribute.IncludeExceptionDetailInFaults ou ServiceDebugBehavior.IncludeExceptionDetailInFaults definida como true, o cliente experimenta isso como um tipo FaultException<TDetail> não declarado do tipo ExceptionDetail. Os clientes podem capturar essa falha específica ou manipular a falha em um bloco de captura para FaultException.
Normalmente, somente FaultException<TDetail>, TimeoutExceptione CommunicationException exceções são de interesse para clientes e serviços.
Observação
Outras exceções, é claro, ocorrem. Exceções inesperadas incluem falhas catastróficas como System.OutOfMemoryException; normalmente, os aplicativos não devem capturar esses métodos.
Capturar exceções de falha na ordem correta
Como FaultException<TDetail> deriva de FaultException, e FaultException deriva de CommunicationException, é importante capturar essas exceções na ordem adequada. Se, por exemplo, você tiver um bloco try/catch no qual você captura CommunicationExceptionprimeiro, todas as falhas SOAP especificadas e não especificadas são tratadas lá; todos os blocos de captura subsequentes para lidar com uma exceção personalizada FaultException<TDetail> nunca são invocados.
Lembre-se de que uma operação pode retornar qualquer número de falhas especificadas. Cada falha é um tipo exclusivo e deve ser tratada separadamente.
Manipular exceções ao fechar o canal
A maior parte da discussão anterior tem a ver com falhas enviadas no curso do processamento de mensagens de aplicativo, ou seja, mensagens enviadas explicitamente pelo cliente quando o aplicativo cliente chama operações no objeto cliente WCF.
Mesmo com objetos locais descartando o objeto, é possível gerar ou mascarar exceções que ocorrem durante o processo de reciclagem. Algo semelhante pode ocorrer quando você usa objetos cliente WCF. Ao chamar operações, você está enviando mensagens por uma conexão estabelecida. Fechar o canal pode gerar exceções se a conexão não puder ser fechada ou se já estiver fechada, mesmo que todas as operações tenham sido retornadas corretamente.
Normalmente, os canais de objeto do cliente são fechados de uma das seguintes maneiras:
Quando o objeto cliente WCF é reciclado.
Quando o aplicativo cliente chama ClientBase<TChannel>.Close.
Quando o aplicativo cliente chama ICommunicationObject.Close.
Quando o aplicativo cliente chama uma operação que é uma operação de encerramento para uma sessão.
Em todos os casos, o fechamento do canal instrui o canal a começar a fechar todos os canais subjacentes que possam estar enviando mensagens para dar suporte a funcionalidades complexas no nível do aplicativo. Por exemplo, quando um contrato exige sessões, uma associação tenta estabelecer uma sessão trocando mensagens com o canal de serviço até que uma sessão seja estabelecida. Quando o canal é fechado, o canal de sessão subjacente notifica o serviço de que a sessão é encerrada. Nesse caso, se o canal já tiver abortado, fechado ou estiver inutilizável (por exemplo, quando um cabo de rede estiver desconectado), o canal cliente não poderá informar ao canal de serviço que a sessão foi encerrada e pode resultar em uma exceção.
Anular o canal, se necessário
Como fechar o canal também pode gerar exceções, recomendamos que, além de capturar exceções de falha na ordem correta, você anule o canal usado para fazer a chamada no bloco de captura.
Se a falha transmitir informações de erro específicas a uma operação e permanecer possível que outras pessoas possam usá-la, não será necessário anular o canal (embora esses casos sejam raros). Em todos os outros casos, é recomendável anular o canal. Para obter um exemplo que demonstra todos esses pontos, consulte Exceções Esperadas.
O exemplo de código a seguir mostra como lidar com exceções de falha SOAP em um aplicativo cliente básico, incluindo uma falha declarada e uma falha não declarada.
Observação
Este código de exemplo não usa o using constructo. Como os canais de fechamento podem gerar exceções, é recomendável que os aplicativos criem um cliente WCF primeiro e, em seguida, abram, usem e fechem o cliente WCF no mesmo bloco try. Para obter detalhes, consulte Visão geral do cliente do WCF e use Close and Abort para liberar recursos de cliente do WCF.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;
public class Client
{
public static void Main()
{
// Picks up configuration from the config file.
SampleServiceClient wcfClient = new SampleServiceClient();
try
{
// Making calls.
Console.WriteLine("Enter the greeting to send: ");
string greeting = 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 (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (FaultException<GreetingFault> greetingFault)
{
Console.WriteLine(greetingFault.Detail.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (FaultException unknownFault)
{
Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
Console.ReadLine();
wcfClient.Abort();
}
}
}
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