WCF: forneça FaultException genérica em IErrorHandler

Algum contexto: Temos um XSD personalizado e geramos o código WSDL e C # usando WSCF.blue. O lado do cliente usaChannelFactory<T> e compartilha a interface que inclui todos os atributos adicionados pelo WSCF.blue para corresponder ao que está no XSD.

Estou tentando implementarIErrorHandler.ProvideFault onde ele fornece um genéricoFaultException<T>, mas no lado do cliente estou recebendo de volta um não genéricoFaultContract. Isto é o que meuProvideFault O método se parece com:

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
    if (!(error is FaultException))
    {
        FaultException faultException = FaultExceptionFactory.CreateFaultException(error);
        MessageFault messageFault = faultException.CreateMessageFault();
        fault = Message.CreateMessage(version, messageFault, faultException.Action);
    }
}

Em cada método de serviço, se eu tentar / capturar comthrow FaultExceptionFactory.CreateFaultException(ex) funciona como esperado, então eu acho que o[FaultContract], fábrica, ligações, etc. estão todos corretos. Por precaução, é assim que a fábrica funciona:

BusinessRuleFaultExceptionType businessRuleFaultException = new BusinessRuleFaultExceptionType();
BusinessRuleFaultException.Code = exception.Code.ToString();
BusinessRuleFaultException.Reason = exception.Message;
return new FaultException<BusinessRuleFaultExceptionType>(
    businessRuleFaultException,
    exception.Message,
    new FaultCode(exception.Code.ToString())
);

Eu acho que o problema é como a mensagem é criada emIErrorHandler, talvez emCreateMessageFault(). Eu li que a ação deve serfaultException.Action ao invés denull, mas de fatofaultException.Action énull. Talvez isso esteja causando o problema. Posso definir uma ação na fábrica, mas qual deve ser a ação e por que isso não aparece com o lançamento manual?

Alguma outra idéia do que eu possa estar perdendo?

Editar: Eu verifiquei o WSDL e encontrei a operação específica que estava chamando e sua ação:

<wsdl:operation name="MyMethod">
<wsdl:fault wsaw:Action="http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault" name="BusinessRuleFaultExceptionTypeFault" message="tns:..."/>

Eu tentei codificar a ação:Message.CreateMessage(..., "http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault") e configurá-lo para o.Action na fábrica, mas isso ainda não funcionou.

Edição 2: O throw / catch gera o seguinte XML que permite capturar a exceção genérica no cliente:

<s:Fault>
    <faultcode xmlns="">s:-100</faultcode>
    <faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
    <detail xmlns="">
        <BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Code xmlns="http://myNamespace/Entitites">-100</Code>
            <Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
        </BusinessRuleFaultExceptionType>
    </detail>
</s:Fault>

oIHttpErrorHandler gera o seguinte que vai para o não genéricoFaultException:

<s:Fault>
    <faultcode xmlns="">s:-100</faultcode>
    <faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
    <detail xmlns="">
        <BusinessRuleFaultExceptionType xmlns="http://schemas.datacontract.org/2004/07/My.Dot.Net.Namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <codeField>-100</codeField>
            <reasonField>xxx</reasonField>
        </BusinessRuleFaultExceptionType>
    </detail>
</s:Fault>

Edição 3: Se eu adicionar[DataContract] e[DataMember] aoBusinessRuleFaultExceptionType, então recebo quase o XML correto:

<s:Fault>
    <faultcode xmlns="">s:-100</faultcode>
    <faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
    <detail xmlns="">
        <BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <Code>-100</Code>
            <Reason>xxx</Reason>
        </BusinessRuleFaultExceptionType>
    </detail>
</s:Fault>

Está faltando o espaço para nome de Código e Razão. Pelo menos eu acho que isso diminui. A serialização regular está usando o[XmlType] e[XmlElement] enquanto oIErrorHandler está usando[DataContract] e[DataMember]. Infelizmente[DataMember] não permite definir o espaço para nome, então acho que a questão agora é como usar o XMLSerializer noIErrorHandler. Isso descreve meu problema, mas a correção não funcionará pelo motivo indicado acima:http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html

Edição 4: Encontrei parcialmente o problema. Nós estamos usandoXmlSerializer, mas desdeIErrorHandler está fora do escopo da operação, ele volta ao padrãoDataContractSerializer. A solução é alterar seu serviço para usarDataContractSerializer em qualquer lugar ou escolha manualmenteXmlSerializer ao criar as falhas. Esses dois artigos forneceram o que eu precisava:

http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html http://zamd.net/2008/08/15/serializing-faults-using-xmlserializer/

Isso me deixamuito Fechar. É o mesmo que o XML de trabalho, exceto que o namespace do tipo de exceção está ausente:

<s:Fault>
    <faultcode xmlns="">s:-100</faultcode>
    <faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
    <detail xmlns="">
        <BusinessRuleFaultExceptionType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Code xmlns="http://myNamespace/Entitites">-100</Code>
            <Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
        </BusinessRuleFaultExceptionType>
    </detail>
</s:Fault>

Presumo que não adicionexmlns="http://myNamespace/Services" porque não possui o contexto da solicitação. Esse espaço para nome é definido na interface, mas não o contrato de dados. Eu realmente serei forçado a permanecer dentro do contexto da solicitação (esperoIOperationInvoker funciona), em vez de usarIHttpHandler?

questionAnswers(2)

yourAnswerToTheQuestion