Présentation : cette section décrit principalement les exceptions et les exceptions simulées qui peuvent se produire dans les appels de service, et analyse quand et quelles exceptions peuvent être interceptées, et comment transmettre correctement les exceptions de service au client.
À la fin de l'article, la séquence de capture pour détecter correctement les exceptions est donnée. Cette capture d'exception n'est qu'une introduction, et certaines d'entre elles concernent des fonctions d'application, donc le code et l'écriture sont relativement simples. Elle introduit également certaines techniques de gestion des exceptions côté serveur.
1. Tout d’abord, nous créons un serveur et un client de calculatrice simple, comme suit :
Cliquez pour développer le code
//Serveur[ServiceContract]interface publique ICalc{[OperationContract][FaultContract(typeof(GreentingError))]string Div(int x, int y);}classe publique Calc : ServiceBase, ICalc {chaîne publique Div(int x, int y ) ) {string result = string.Empty; try {result = string.Format("result: {0}", x / y); } catch (DivideByZeroException ex) {throw ex; [ServiceContract] interface publique ICalc { [OperationContract] [FaultContract(typeof(GreentingError))] string Div(int x, int y); ) ) {retour base.Channel.Div(x, y }});
Bon, j'avoue que le code est assez simple, mais j'aime les choses simples.
2. Les choses simples sont bonnes, et les appeler est beaucoup plus simple ;
essayez { CalcClientcalcclient = new CalcClient(); string result =calcclient.Div(10, 0); Console.WriteLine(result); Console.ReadKey(); ex) {lancer ex; } catch (FaultExceptionex) {lancer ex; catch (System.ServiceModel.CommunicationException ex) {lancer ex;
3. Lorsque nous appelons la méthode Div(int x, int y) du service et transmettons la valeur 0 au logarithme y, le serveur lèvera une exception DivideByZeroException, ce qui est attendu. A cette époque,
Cette exception est interceptée dans la section FaultException du client.
4. Pas de problème, nous lancerons manuellement FaultException dans le code du serveur.
catch (DivideByZeroException ex){FaultException exception = new FaultException (ex.Message);}
À ce moment-là, j'ai découvert que FaultException avait détecté cette exception. Pourquoi ?
5. Faites un autre test.
Ajoutez ce code au service : System.Threading.Thread.Sleep(70000); pour provoquer l'expiration du service.
Cette fois, TimeOutException a finalement intercepté l'exception du serveur, nous devons donc nous demander quand FaultException<GreentingError> interceptera-t-il l'exception ? La réponse est que lorsque le serveur lance FaultException<GreentingError>, citez un passage sur MSDN (partie verte) :
Si l'écouteur reçoit une erreur SOAP qui n'est pas attendue ou spécifiée dans le contrat d'opération, un objet FaultException sera généré. Deux types d'erreurs SOAP peuvent être envoyées : déclarées et non déclarées. Une erreur SOAP déclarée est une erreur dans laquelle une opération possède l'attribut System.ServiceModel.FaultContractAttribute qui spécifie un type d'erreur SOAP personnalisé. Les erreurs SOAP non déclarées sont des erreurs qui ne sont pas spécifiées dans le contrat de l'opération. L'« erreur SOAP inattendue ou non spécifiée » fait ici référence à un type d'erreur personnalisé qui n'est pas encapsulé avec FaultContractAttribute dans l'opération de service.
6. Alors, quand CommincationException sera-t-elle détectée ?
MSDN dit : L'application gère les objets CommunicationException qui peuvent être lancés pendant la communication
Eh bien, afin de déclencher cette exception, nous procédons comme suit. Fermez d’abord l’objet canal actuel sur le serveur.
OperationContext.Current.Channel.Close();
Malheureusement, le client n'a pas intercepté CommunicationException, mais a intercepté TimeOutException ! Étant donné qu'aucune exception ne s'est produite après la fermeture du canal de service, aucun message n'a été renvoyé au client. Après avoir attendu un certain temps, le client a expiré et s'est arrêté.
Nous spécifions donc un TimeSpan lors de la fermeture du canal. Cela permet à l'appel de revenir immédiatement. Bien entendu, le retour d'appel peut également être effectué via Channel.Abort.
OperationContext.Current.Channel.Close(new TimeSpan(5000));
Lors de l'appel de la méthode Close de IContextChannel, spécifiez l'heure à laquelle l'opération d'envoi doit être terminée avant l'expiration du délai, afin que le message puisse être renvoyé immédiatement dans le délai spécifié sans avoir à attendre l'expiration de l'appel de service, sinon le client lancera définitivement une exception TimeOutException au lieu de l'exception CommunicationException.
7. Remèdes
Dans le même temps, afin de prendre des mesures correctives lorsqu'une exception se produit dans le service, nous avons créé une nouvelle classe abstraite ServiceBase et en avons fait hériter la classe d'implémentation du service Calc, afin que nous puissions prendre le contrôle des différentes transitions d'état de le service. La classe ServiceBase est la suivante :
classe partielle abstraite publique ServiceBase { canal privé IContextChannel = null; protégé ServiceBase() { canal = OperationContext.Current.Channel; canal.Opening += new EventHandler (délégué (expéditeur d'objet, EventArgs e) {/* À FAIRE */ }) ; canal.Opened += new EventHandler(délégué(objet expéditeur, EventArgs e) {/* TO DO*/ }); canal.Closing += new EventHandler(délégué(objet expéditeur, EventArgs e) {/* TO DO*/ }); canal.Closed += new EventHandler(délégué(expéditeur d'objet, EventArgs e) { Abort(); }); canal.Faulted += new EventHandler(délégué(expéditeur d'objet, EventArgs e) { Abort(); }) ; } void Open() {/* TO DO*/ } void Close() { /* TO DO*/} void Abort() { canal.Abort( }}
Comme le montre le code ci-dessus, une fois le canal de service fermé, nous arrêtons immédiatement le service et laissons le message revenir immédiatement. À ce moment, même si le service est fermé pendant l'opération sans spécifier l'heure d'expiration du délai, l'appel. peut toujours revenir immédiatement.
Cette fois, le client a finalement détecté l'exception CommunicationException, comme le montre la figure ci-dessous :
Pourquoi cela se produit-il ?
8. Jetons un coup d'œil à la hiérarchie d'héritage de CommunicationException, dont nous pouvons nous inspirer.
8.1. Le premier est la hiérarchie d'héritage de FaultException<TDetail>.
8.2, encore une fois la hiérarchie d'héritage de TimeOutException.
9. Comme le montre la figure ci-dessus, TimeOutException et CommunicationException héritent tous deux de la classe SystemException, tandis que FaultException hérite de CommunicationException et enfin FaultException<TDetail> hérite de la classe FaultException.
10. Enfin, nous avons conclu que l'ordre correct pour détecter les exceptions sur le client devrait être :
TimeOutException> FaultException<TDetail> > FaultException > CommunicationException > Exception. Il est fortement recommandé aux développeurs de lancer et d’intercepter des exceptions de type FaultException<TDetail>.
Auteur : Lao Mi Source : http://www.cnblogs.com/viter/
Le droit d'auteur de cet article appartient à l'auteur et à Blog Park. La réimpression est la bienvenue. Cependant, cette déclaration doit être conservée sans le consentement de l'auteur et un lien vers le texte original doit être fourni à un endroit évident sur la page de l'article. le droit de poursuivre la responsabilité juridique est réservé.