Pergunta

Eu estou a experimentar usando o FaultException e FaultException<T> para determinar o melhor padrão de uso em nossas aplicações.Precisamos de apoio WCF, bem como a não-serviço WCF consumidores/clientes, incluindo SOAP 1.1 e SOAP 1.2 clientes.

FYI:usando FaultExceptions com wsHttpBinding resultados em SOAP 1.2 semântica enquanto o uso de FaultExceptions com basicHttpBinding resultados em SOAP 1.1 semântica.

Eu estou usando o seguinte código para lançar um FaultException<FaultDetails>:

  throw new FaultException<FaultDetails>(
      new FaultDetails("Throwing FaultException<FaultDetails>."),
      new FaultReason("Testing fault exceptions."),
      FaultCode.CreateSenderFaultCode(new FaultCode("MySubFaultCode"))
      );

O FaultDetails classe é apenas uma simples classe de teste que contém uma cadeia de propriedade de "Mensagem" como você pode ver abaixo.

Quando utilizar o wsHttpBinding a resposta é:

<?xml version="1.0" encoding="utf-16"?>
<Fault xmlns="http://www.w3.org/2003/05/soap-envelope">
<Code>
  <Value>Sender</Value>
  <Subcode>
    <Value>MySubFaultCode</Value>
  </Subcode>
</Code>
<Reason>
  <Text xml:lang="en-US">Testing fault exceptions.</Text>
</Reason>
<Detail>
  <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Message>Throwing FaultException&lt;FaultDetails&gt;.</Message>
  </FaultDetails>
</Detail>

Isso parece certo de acordo com o SOAP 1.2 especificações.Principal/de raiz "Código" é "Remetente", que tem um "Sub" de "MySubFaultCode".Se o consumidor de serviço/cliente está usando WCF o FaultException no lado do cliente também imita a mesma estrutura, com o faultException.Código.Nome ser "Remetente" e faultException.Código.O subcódigo.Nome ser "MySubFaultCode".

Quando utilizar basicHttpBinding a resposta é:

<?xml version="1.0" encoding="utf-16"?>
<s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <faultcode>s:MySubFaultCode</faultcode>
  <faultstring xml:lang="en-US">Testing fault exceptions.</faultstring>
  <detail>
    <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <Message>Throwing FaultException&lt;FaultDetails&gt;.</Message>
    </FaultDetails>
  </detail>
</s:Fault>

Isso não olhar para a direita.Olhando para o SOAP 1.1 especificações, eu estava esperando para ver o "faultcode" para ter um valor de "s:Client.MySubFaultCode" quando eu uso FaultCode.CreateSenderFaultCode(nova FaultCode("MySubFaultCode")).Também um cliente WCF recebe incorreta de uma estrutura.O faultException.Código.O nome é "MySubFaultCode" em vez de "Remetente", e o faultException.Código.O subcódigo é nulo em vez de faultException.Código.O subcódigo.Nome ser "MySubFaultCode".Além disso, o faultException.Código.IsSenderFault é falso.

Problema semelhante quando utilizar FaultCode.CreateReceiverFaultCode(nova FaultCode("MySubFaultCode")):

  • funciona como esperado para SOAP 1.2
  • gera "s:MySubFaultCode" em vez de "s:Server.MySubFaultCode" e o faultException.Código.IsReceiverFault é falso para SOAP 1.1

Este item também foi postado por alguém em http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1 em 2006 e ninguém respondeu.Acho muito difícil acreditar que ninguém foi executado para isso, ainda.

Aqui está alguém a ter um problema semelhante: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110&SiteID=1&mode=1

Microsoft Connect erro: https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=367963

Descrição de como falhas deve funcionar: http://blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx

Estou fazendo algo errado ou é realmente um bug no WCF?

Foi útil?

Solução

Esta é a minha solução actual:

    /// <summary>
    /// Replacement for the static methods on FaultCode to generate Sender and Receiver fault codes due
    /// to what seems like bugs in the implementation for basicHttpBinding (SOAP 1.1). wsHttpBinding 
    /// (SOAP 1.2) seems to work just fine.
    /// 
    /// The subCode parameter for FaultCode.CreateReceiverFaultCode and FaultCode.CreateSenderFaultCode
    /// seem to take over the main 'faultcode' value in the SOAP 1.1 response, whereas in SOAP 1.2 the
    /// subCode is correctly put under the 'Code->SubCode->Value' value in the XML response.
    /// 
    /// This workaround is to create the FaultCode with Sender/Receiver (SOAP 1.2 terms, but gets
    /// translated by WCF depending on the binding) and an agnostic namespace found by using reflector
    /// on the FaultCode class. When that NS is passed in WCF seems to be able to generate the proper
    /// response with SOAP 1.1 (Client/Server) and SOAP 1.2 (Sender/Receiver) fault codes automatically.
    /// 
    /// This means that it is not possible to create a FaultCode that works in both bindings with
    /// subcodes.
    /// </summary>
    /// <remarks>
    /// See http://stackoverflow.com/questions/65008/net-wcf-faults-generating-incorrect-soap-11-faultcode-values
    /// for more details.
    /// </remarks>
    public static class FaultCodeFactory
    {
        private const string _ns = "http://schemas.microsoft.com/ws/2005/05/envelope/none";

        /// <summary>
        /// Creates a sender fault code.
        /// </summary>
        /// <returns>A FaultCode object.</returns>
        /// <remarks>Does not support subcodes due to a WCF bug.</remarks>
        public static FaultCode CreateSenderFaultCode()
        {
            return new FaultCode("Sender", _ns);
        }

        /// <summary>
        /// Creates a receiver fault code.
        /// </summary>
        /// <returns>A FaultCode object.</returns>
        /// <remarks>Does not support subcodes due to a WCF bug.</remarks>
        public static FaultCode CreateReceiverFaultCode()
        {
            return new FaultCode("Receiver", _ns);
        }
    }

Infelizmente, eu não vejo uma maneira de usar subcódigos, sem interromper o SOAP 1.1 ou 1.2 clientes.

Se você usar o Código.O subcódigo de sintaxe, você pode criar SOAP 1.1 compatível faultcode valores, mas ele quebra SOAP 1.2.

Se você usar o bom subcódigo apoio .NET (através da estática FaultCode métodos ou uma das sobrecargas) quebra SOAP 1.1, mas funciona em SOAP 1.2.

Outras dicas

Resposta da Microsoft:

Como discutido em http://msdn.microsoft.com/en-us/library/ms789039.aspx, existem dois métodos descritos na especificação Soap 1.1 para os códigos de falha personalizadas:

(1) Usando a notação "ponto", como lhe chama,

(2) a Definição inteiramente novos códigos de falha

Infelizmente, a notação "ponto" deve ser evitado, uma vez que o uso é desencorajado em WS-I Basic Profile especificação.Essencialmente, isto significa que não há real equivalente a Soap 1.2 falha Subcódigo quando usando Soap 1.1.

Assim, ao gerar falhas, você terá que ter consciência de MessageVersion definido na ligação, e gerar faultcodes de acordo.

Desde o "emissor" e "receptor" não válido códigos de falha de Soap 1.1, e que não é equivalente a uma falha subcódigo, você não deve usar o CreateSenderFaultCode e CreateReceiverFaultCode métodos de geração de costume códigos de falha de Soap 1.1.

Em vez disso, você precisará definir o seu próprio faultcode, usando o seu próprio espaço de nomes e o nome:

FaultCode customFaultCode = new FaultCode(nome local, faultNamespace);

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top