4 votes

Lancer FaultException générique

J'ai un service WCF qui, en cas de problème, lance une FaultException générique. Je ne sais pas pourquoi, parfois les clients attrapent plutôt une FaultException non générique au lieu de l'exception générique.

Est-ce que quelqu'un sait quel est le problème?

18voto

Darin Dimitrov Points 528142

Votre service doit gérer toutes les exceptions et les encapsuler dans FaultException où T est un contrat de données que vous avez écrit. Ainsi, la première étape consiste à définir un contrat de données personnalisé qui contiendra les informations sur votre exception :

[DataContract]
public class CustomFault
{
    public string Message { get; set; }
}

Ensuite, vous indiquez à votre contrat de service que ses méthodes pourraient potentiellement générer une FaultException. Cela permet au service d'exposer la classe CustomFault dans le wsdl, afin que les clients puissent générer une classe proxy :

[ServiceContract]
public interface IMyServiceContract
{
    [FaultContract(typeof(CustomFault))]
    void MyMethod(string someArgument);
}

La prochaine étape consiste à implémenter cette interface :

public class MyService : IMyServiceContract
{
    public void MyMethod(string someArgument)
    {
        // Faites quelque chose ici qui pourrait générer des exceptions mais ne les attrapez pas encore
    }
}

Pour gérer les exceptions, vous pouvez implémenter IErrorHandler qui sera utilisé chaque fois qu'une des méthodes de votre service générera une exception. Le but de ce gestionnaire d'erreur est d'encapsuler l'exception dans FaultException :

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
    {
        var customFault = new CustomFault()
        {
            Message = error.Message,
        };
        var fe = new FaultException(customFault);
        MessageFault fault = fe.CreateMessageFault();
        string ns = "http://somenamespace/whatever";
        msg = Message.CreateMessage(version, fault, ns);
    }
}

Une fois que vous avez enregistré votre gestionnaire d'erreurs, du côté client, vous obtiendrez toujours FaultException.

5voto

Drew Points 339

Si votre client n'a pas accès au type d'exception lui-même (le sur FaultException), alors la version non générique de FaultException est lancée. J'ai passé des heures à essayer de comprendre cela, et j'ai finalement réalisé quand j'ai trouvé cela sur les forums msdn. Ce serait bien s'il y avait une indication que l'exception a été modifiée avant d'être lancée hors du service, mais ce n'est pas le cas.

2voto

John Saunders Points 118808

La non-générique FaultException est levée lorsque le service lance une autre exception qui n'est pas capturée. Vous devrez découvrir quelle est l'exception et la corriger s'il s'agit d'un bug, ou décider s'il s'agit de quelque chose que vous voulez exposer à vos clients, puis l'encapsuler dans une FaultException générique et ajouter un FaultContract de manière appropriée.

2voto

mostlytech Points 641

Une autre possibilité est que votre TDetail ne soit pas correctement sérialisé. Cela peut être le cas si, par exemple, TDetail dérive de Exception et que vous avez une exception interne qui n'est pas sérialisable.

1voto

Greg Sansom Points 9059

Cela se produira si vous n'avez pas déclaré votre type de détail de faute avec un FaultContractAttribute.

Voici à quoi devrait ressembler votre contrat de service :

[ServiceContract]
public interface IMyServiceContract
{
    //...
    [OperationContract]
    [FaultContract(typeof(MyFaultDetail))]
    [FaultContract(typeof(OtherFaultDetail))] 
    GetDetailsResp GetDetails(GetDetailsReq req);
    //...
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X