WCF: proporcione FaultException genérico en IErrorHandler

Algún contexto: tenemos un XSD personalizado y generamos el código WSDL y C # usando WSCF.blue. El lado del cliente usaChannelFactory<T> y comparte la interfaz que incluye todos los atributos agregados por WSCF.blue para que coincida con lo que está en el XSD.

Estoy tratando de implementarIErrorHandler.ProvideFault donde proporciona un genéricoFaultException<T>, pero en el lado del cliente estoy obteniendo un no genéricoFaultContract. Esto es lo que miProvideFault El método se ve así:

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);
    }
}

En cada método de servicio, si hago un try / catch conthrow FaultExceptionFactory.CreateFaultException(ex) funciona como se esperaba, así que creo que el[FaultContract], fábrica, enlaces, etc. son todos correctos. Por si acaso, así es como funciona la fábrica:

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())
);

Creo que el problema es cómo se crea el mensaje enIErrorHandler, tal vez enCreateMessageFault(). He leído que la acción debería serfaultException.Action en lugar denull, Pero, de hechofaultException.Action esnull. Quizás esto esté causando el problema. Puedo establecer una acción en la fábrica, pero ¿cuál debería ser la acción y por qué no aparecería eso con el lanzamiento manual?

¿Alguna otra idea de lo que podría estar perdiendo?

Editar: Revisé el WSDL y encontré la operación específica que estaba llamando y su acción:

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

Traté de codificar la acción:Message.CreateMessage(..., "http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault") y poniéndolo a la.Action en la fábrica pero eso todavía no funcionó.

Edición 2: Throw / catch genera el siguiente XML que permite detectar la excepción genérica en el 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>

losIHttpErrorHandler genera lo siguiente que va al no 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>

Edición 3: Si agrego[DataContract] y[DataMember] alBusinessRuleFaultExceptionType, entonces obtengo casi el XML correcto:

<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>

Le falta el espacio de nombres para Código y razón. Al menos creo que esto lo reduce. La serialización regular está utilizando el[XmlType] y[XmlElement] mientras que laIErrorHandler esta usando[DataContract] y[DataMember]. Desafortunadamente[DataMember] no le permite configurar el espacio de nombres, por lo que creo que la pregunta ahora es cómo usar XMLSerializer enIErrorHandler. Esto describe mi problema, pero la solución no funcionará por la razón indicada anteriormente:http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html

Edición 4: Encontré parcialmente el problema. Estamos usandoXmlSerializer, pero desdeIErrorHandler está fuera del alcance de la operación, vuelve al valor predeterminadoDataContractSerializer. La solución es cambiar su servicio para usarDataContractSerializer en todas partes, o elegir manualmenteXmlSerializer al crear las fallas. Estos dos artículos proporcionaron lo que necesitaba:

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

Eso me atrapamuy cerrar. Es lo mismo que el XML de trabajo, excepto que falta el espacio de nombres del tipo de excepción:

<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>

Supongo que no agregaxmlns="http://myNamespace/Services" porque no tiene el contexto de la solicitud. Ese espacio de nombres se define en la interfaz, pero no en el contrato de datos. ¿Realmente me veré obligado a permanecer dentro del contexto de la solicitud?IOperationInvoker funciona), en lugar de usarIHttpHandler?

Respuestas a la pregunta(2)

Su respuesta a la pregunta