Definindo e especificando falhas
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. Este tópico aborda quando e como definir o conteúdo de falha personalizado e especificar quais operações podem retorná-lo. Para obter mais informações sobre como um serviço ou cliente duplex, pode enviar essas falhas e como um cliente ou aplicativo de serviço trata essas falhas, consulte Envio e Recebimento de Falhas. Para obter uma visão geral do tratamento de erros em aplicativos WCF (Windows Communication Foundation), consulte Especificando e tratando falhas em contratos e serviços.
Visão geral
Falhas de SOAP declaradas são aquelas em que uma operação tem um System.ServiceModel.FaultContractAttribute que especifica um tipo de falha de SOAP personalizada. Falhas de SOAP não declaradas são aquelas que não são especificadas no contrato para uma operação. Este tópico ajuda você a identificar essas condições de erro e criar um contrato de falha para o serviço que os clientes podem usar para tratar corretamente essas condições de erro quando notificados por falhas de SOAP personalizadas. As tarefas básicas são, em ordem:
Defina as condições de erro das quais um cliente do serviço deve saber.
Defina o conteúdo personalizado das falhas de SOAP para essas condições de erro.
Marque suas operações para que as falhas de SOAP específicas que elas geram sejam expostas aos clientes em linguagem WSDL.
Definindo as condições de erro que os clientes devem conhecer
As falhas de SOAP são mensagens descritas publicamente que carregam informações de falha para uma operação específica. Como elas são descritas junto a outras mensagens de operação em WSDL, os clientes sabem e, portanto, esperam tratar essas falhas ao invocar uma operação. No entanto, como os serviços WCF são gravados em código gerenciado, decidir quais condições de erro no código gerenciado devem ser convertidas em falhas e retornadas ao cliente oferece a oportunidade de separar condições de erro e bugs em seu serviço da conversa formal de erro que você tem com um cliente.
Por exemplo, o exemplo de código a seguir mostra uma operação que usa dois inteiros e retorna outro inteiro. Várias exceções podem ser geradas aqui, portanto, ao projetar o contrato de falha, você deve determinar quais condições de erro são importantes para o cliente. Nesse caso, o serviço deve detectar a System.DivideByZeroExceptionexceção.
[ServiceContract]
public class CalculatorService
{
[OperationContract]
int Divide(int a, int b)
{
if (b==0) throw new Exception("Division by zero!");
return a/b;
}
}
<ServiceContract> _
Public Class CalculatorService
<OperationContract> _
Public Function Divide(a As Integer, b As Integer) As Integer
If b = 0 Then Throw New DivideByZeroException("Division by zero!")
Return a / b
End Function
End Class
No exemplo anterior, a operação pode retornar uma falha de SOAP personalizada específica para a divisão por zero, uma falha personalizada específica para as operações matemáticas, mas que contém informações específicas para dividir por zero, várias falhas para diversas situações de erro diferentes ou nenhuma falha de SOAP.
Definir o conteúdo das condições de erro
Após identificar uma condição de erro como uma que pode retornar de forma útil uma falha de SOAP personalizada, a próxima etapa é definir o conteúdo dessa falha e garantir que a estrutura de conteúdo possa ser serializada. O exemplo de código na seção anterior mostra um erro específico a uma operação Divide
, mas se houver outras operações no serviço Calculator
, uma única falha de SOAP personalizada poderá informar ao cliente de todas as condições de erro da calculadora, incluindo as Divide
. O exemplo de código a seguir mostra a criação de uma falha de SOAP personalizada, MathFault
, que pode relatar erros feitos usando todas as operações matemáticas, incluindo Divide
. Embora a classe possa especificar uma operação (a propriedade Operation
) e um valor descrever o problema (a propriedade ProblemType
), a classe e essas propriedades devem ser serializáveis para serem transferidas para o cliente em uma falha de SOAP personalizada. Portanto, os atributos System.Runtime.Serialization.DataContractAttribute e System.Runtime.Serialization.DataMemberAttribute são usados para tornar o tipo e suas propriedades serializáveis e o mais interoperáveis possível.
// Define a math fault data contract
[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public class MathFault
{
private string operation;
private string problemType;
[DataMember]
public string Operation
{
get { return operation; }
set { operation = value; }
}
[DataMember]
public string ProblemType
{
get { return problemType; }
set { problemType = value; }
}
}
' Define a math fault data contract
<DataContract([Namespace]:="http://Microsoft.ServiceModel.Samples")> _
Public Class MathFault
Private m_operation As String
Private m_problemType As String
<DataMember()> _
Public Property Operation() As String
Get
Return m_operation
End Get
Set(ByVal value As String)
m_operation = value
End Set
End Property
<DataMember()> _
Public Property ProblemType() As String
Get
Return m_problemType
End Get
Set(ByVal value As String)
m_problemType = value
End Set
End Property
End Class
Para obter mais informações sobre como garantir que seus dados sejam serializáveis, consulte Especificando a transferência de dados de entrada de contratos de serviço. Para obter uma lista do suporte à serialização que fornece System.Runtime.Serialization.DataContractSerializer, consulte os Tipos compatíveis com o serializador de contrato de dados.
Marcar operações para estabelecer o contrato de falha
Após a definição da estrutura de dados serializável retornada como parte de uma falha SOAP personalizada, a última etapa é marcar seu contrato de operação como gerando uma falha de SOAP desse tipo. Para fazer isso, use o atributo System.ServiceModel.FaultContractAttribute e passe o tipo do tipo de dados personalizado que você construiu. O exemplo de código a seguir mostra como usar o atributo FaultContractAttribute para especificar que a operação Divide
pode retornar uma falha de SOAP do tipo MathFault
. Outras operações baseadas em matemática agora também podem especificar que podem retornar um MathFault
.
[OperationContract]
[FaultContract(typeof(MathFault))]
int Divide(int n1, int n2);
<OperationContract()> _
<FaultContract(GetType(MathFault))> _
Function Divide(ByVal n1 As Integer, ByVal n2 As Integer) As Integer
Uma operação pode especificar que ela retorna mais de uma falha personalizada marcando essa operação com mais de um atributo FaultContractAttribute.
A próxima etapa, para implementar o contrato de falha na implementação da operação, é descrita no tópico Envio e Recebimento de Falhas.
Considerações sobre SOAP, WSDL e Interoperabilidade
Em algumas circunstâncias, especialmente ao interoperar com outras plataformas, pode ser importante controlar a forma como uma falha aparece em uma mensagem SOAP ou a maneira como ela é descrita nos metadados do WSDL.
O atributo FaultContractAttribute tem uma propriedade Name que permite o controle do nome do elemento de falha WSDL gerado nos metadados para essa falha.
De acordo com o padrão SOAP, uma falha pode ter um Action
, um Code
e um Reason
. A Action
é controlada pela propriedade Action. A propriedade Code e a propriedade Reason são ambas propriedades da classe System.ServiceModel.FaultException, que é a classe pai do genérico System.ServiceModel.FaultException<TDetail>. A propriedade Code
inclui um membro SubCode.
Ao acessar não-serviços que geram falhas, existem determinadas limitações. O WCF dá suporte somente a falhas com tipos de detalhes que o esquema descreve e que são compatíveis com contratos de dados. Por exemplo, conforme mencionado acima, o WCF não dá suporte a falhas que usam atributos XML em seus tipos de detalhes ou falhas com mais de um elemento de nível superior na seção de detalhes.
Confira também
- FaultContractAttribute
- DataContractAttribute
- DataMemberAttribute
- Especificando e lidando com falhas em contratos e serviços
- Enviando e recebendo falhas
- Como: declarar falhas em contratos de serviço
- Noções básicas de nível de proteção
- Como: definir a propriedade ProtectionLevel
- Especificando transferência de dados em contratos de serviço