2009-03-15 10 views
4

J'ai un service WCF qui, en cas de problème, déclenche une exception FaultException générique. Je ne sais pas pourquoi, parfois les clients vont attraper une exception FaultException générique au lieu de l'exception générique.Lancer FaultException générique

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

Répondre

18

Votre service doit gérer toutes les exceptions et les placer dans FaultException <T> où T est un contrat de données que vous avez écrit. La première étape consiste à définir un contrat de données personnalisé qui contiendra vos informations d'exception:

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

Ensuite, vous demandez à votre contrat de service que ses méthodes pourraient jeter FaultException <CustomFault>. 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); 
} 

L'étape suivante consiste à mettre en œuvre cette interface:

public class MyService : IMyServiceContract 
{ 
    public void MyMethod(string someArgument) 
    { 
     // Do something here that could throw exceptions but don't catch yet 
    } 
} 

Pour gérer les exceptions que vous pourriez mettre en œuvre IErrorHandler qui sera utilisé chaque fois qu'une de vos méthodes de service déclenche une exception. Le but de ce gestionnaire d'erreur est d'envelopper l'exception dans FaultException <CustomFault>:

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>(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 <CustomFault>.

+0

La chose wierd est que la même exception, parfois throws comme une exception FaultException générique. – mrtaikandi

2

Le FaultException non générique est lancé lorsque le service renvoie une autre exception qui n'est pas interceptée. Vous aurez besoin de savoir quelle est l'exception et de la corriger si c'est un bogue, ou bien décider si c'est quelque chose que vous voulez exposer vos clients, puis envelopper dans un FaultException générique et ajouter un FaultContract de manière appropriée.

2

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

5

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

+0

Je n'ai peut-être pas été clair. J'ai utilisé le mot accès en référence à la visibilité de la portée. Ainsi, par exemple, si l'exception est définie en dehors du client et qu'elle n'est marquée sur aucun appel de service avec un attribut FaultContract, la conversion vers le bas se produira car le client n'a pas accès à l'exception. – Drew

1

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

Voici comment votre contrat de service devrait ressembler à:

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

je voyais le même problème et le lien Drew a fourni la réponse posted pour moi. La résolution pour moi était que mon interface de service avait un espace de noms différent de mon défaut de service.

-à-dire, le contrat de service avait:

[ServiceContract(Namespace = "http://dummydomain.com/service/searchservice")] 
    public interface ISearchService 
    .... 

et la faute de service avait:

[DataContract(Namespace = "http://dummydomain.com/service/searchservicefault")] 
public class MySearchServiceFault 
... 

apparemment lorsque les espaces de noms sont différents le client ne sait pas quoi faire avec elle et revient retour au FaultContract non générique ... Je pense que cela dépend un peu du client car j'ai vu le code ci-dessus fonctionner et retourner le FaultContract générique ...

Mais, quand je changé les espaces de noms pour être le même, il semble que le code fonctionne tout le temps dans mes tests.

Questions connexes