Megosztás a következőn keresztül:


Hibák küldése és fogadása

A SOAP-hibák egy szolgáltatásból egy ügyfélnek, kétoldalas esetben pedig egy szolgáltatásba továbbítják a hibaállapot-információkat egymással együttműködő módon. A szolgáltatás általában egyéni hibatartalmakat határoz meg, és meghatározza, hogy mely műveletek adhatják vissza őket. (További információ: Hibák meghatározása és megadása.) Ez a témakör azt ismerteti, hogy egy szolgáltatás- vagy kétoldalas ügyfél hogyan küldheti el ezeket a hibákat a megfelelő hibaállapot bekövetkezésekor, és hogy egy ügyfél vagy szolgáltatásalkalmazás hogyan kezeli ezeket a hibákat. A Windows Communication Foundation (WCF) alkalmazások hibakezelésének áttekintéséért lásd: Szerződések és szolgáltatások hibáinak megadása és kezelése.

SOAP-hibák küldése

A deklarált SOAP-hibák azok, amelyekben egy művelet System.ServiceModel.FaultContractAttribute egyéni SOAP-hibatípust határoz meg. A be nem jelentett SOAP-hibák azok, amelyek nincsenek megadva a műveletre vonatkozó szerződésben.

Deklarált hibák küldése

Deklarált SOAP-hiba küldéséhez észlelje a SOAP-hiba megfelelő hibafeltételét, és küldjön egy újat System.ServiceModel.FaultException<TDetail> , ahol a típusparaméter az adott műveletben FaultContractAttribute megadott típus új objektuma. Az alábbi példakód azt mutatja be, hogy a FaultContractAttribute művelet képes-e SampleMethod SOAP-hibát visszaadni a részletek típusával GreetingFault.

[OperationContract]
[FaultContractAttribute(
  typeof(GreetingFault),
  Action="http://www.contoso.com/GreetingFault",
  ProtectionLevel=ProtectionLevel.EncryptAndSign
  )]
string SampleMethod(string msg);
<OperationContract, FaultContractAttribute(GetType(GreetingFault), Action:="http://www.contoso.com/GreetingFault", ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Function SampleMethod(ByVal msg As String) As String

Ha a GreetingFault hibainformációkat az ügyfélnek szeretné továbbítani, a megfelelő hibafeltételt kell elkapnia, és argumentumként egy új System.ServiceModel.FaultException<TDetail> típusú GreetingFault típust kell megadnia egy új GreetingFault objektummal, ahogyan az alábbi kódpéldában is látható. Ha az ügyfél WCF-ügyfélalkalmazás, ezt felügyelt kivételként tapasztalja, ahol a típus System.ServiceModel.FaultException<TDetail> típusa GreetingFault.

throw new FaultException<GreetingFault>(new GreetingFault("A Greeting error occurred. You said: " + msg));
    Throw New FaultException(Of GreetingFault)(New GreetingFault("A Greeting error occurred. You said: " & msg))
End If

Be nem jelentett hibák küldése

A be nem jelentett hibák küldése nagyon hasznos lehet a WCF-alkalmazások problémáinak gyors diagnosztizálásához és hibakereséséhez, de a hibakeresési eszköz hasznossága korlátozott. Általánosságban elmondható, hogy hibakereséskor ajánlott a ServiceDebugBehavior.IncludeExceptionDetailInFaults tulajdonságot használni. Ha igaz értékre állítja ezt az értéket, az ügyfelek olyan hibákat tapasztalnak, mint a FaultException<TDetail> típus ExceptionDetailkivételei.

Fontos

Mivel a felügyelt kivételek közzétehetik a belső alkalmazásadatokat, beállíthatják ServiceBehaviorAttribute.IncludeExceptionDetailInFaults vagy ServiceDebugBehavior.IncludeExceptionDetailInFaults engedélyezhetik, hogy true a WCF-ügyfelek információt szerezzenek a belső szolgáltatásműveleti kivételekről, beleértve a személyazonosításra alkalmas vagy más bizalmas információkat is.

Ezért a beállítás vagy ServiceDebugBehavior.IncludeExceptionDetailInFaults a beállítás ServiceBehaviorAttribute.IncludeExceptionDetailInFaultstrue csak a szolgáltatásalkalmazások ideiglenes hibakeresésének módjaként javasolt. Ezenkívül egy olyan metódus WSDL-értéke, amely így kezeletlen felügyelt kivételeket ad vissza, nem tartalmazza a FaultException<TDetail> típus szerződését ExceptionDetail. Az ügyfeleknek egy ismeretlen SOAP-hiba (a WCF-ügyfeleknek objektumként System.ServiceModel.FaultException visszaadott) lehetőségére kell számítaniuk a hibakeresési információk megfelelő beszerzéséhez.

Ha be nem jelentett SOAP-hibát szeretne küldeni, dobjon egy System.ServiceModel.FaultException objektumot (vagyis ne az általános típust FaultException<TDetail>), és adja át a sztringet a konstruktornak. Ez kivételként System.ServiceModel.FaultException jelenik meg a WCF-ügyfélalkalmazások számára, ahol a sztring elérhető a FaultException<TDetail>.ToString metódus meghívásával.

Feljegyzés

Ha sztring típusú SOAP-hibát deklarál, majd ezt a szolgáltatásban olyanként FaultException<TDetail> adja meg, ahol a típusparaméter a tulajdonsághoz rendelt sztringérték System.String , és nem érhető el a FaultException<TDetail>.Detail tulajdonságból FaultException<TDetail>.ToString.

Hibák kezelése

A WCF-ügyfelek esetében az ügyfélalkalmazások számára érdekes kommunikáció során előforduló SOAP-hibák felügyelt kivételként jelennek meg. Bár számos kivétel fordulhat elő bármely program végrehajtása során, a WCF-ügyfélprogramozási modellt használó alkalmazások a kommunikáció eredményeként az alábbi két típus kivételeinek kezelésére számíthatnak.

TimeoutException objektumokat dobnak, ha egy művelet túllépi a megadott időtúllépési időtartamot.

CommunicationException az objektumok akkor jelennek meg, ha valamilyen helyreállítható kommunikációs hiba van a szolgáltatáson vagy az ügyfélen.

Az CommunicationException osztály két fontos származtatott típussal FaultException és általános típussal FaultException<TDetail> rendelkezik.

FaultException kivételek akkor keletkeznek, ha a figyelő olyan hibát kap, amely nem várható vagy nem szerepel a műveleti szerződésben; általában ez akkor fordul elő, ha az alkalmazás hibakeresése folyamatban van, és a szolgáltatás tulajdonsága a ServiceDebugBehavior.IncludeExceptionDetailInFaults következőre truevan állítva: .

FaultException<TDetail> a rendszer kivételeket alkalmaz az ügyfélre, ha a műveleti szerződésben meghatározott hiba kétirányú műveletre (azaz egy olyan metódusra) reagál, amelynek OperationContractAttribute az attribútuma IsOneWay a következőre falsevan állítva: ).

Feljegyzés

Ha egy WCF-szolgáltatás rendelkezik az ServiceBehaviorAttribute.IncludeExceptionDetailInFaults ügyfélre true beállított tulajdonságtal, ServiceDebugBehavior.IncludeExceptionDetailInFaults ez be nem jelentett típusként ExceptionDetailjelenik megFaultException<TDetail>. Az ügyfelek elkaphatják ezt az adott hibát, vagy kezelhetik a hibát egy fogási blokkban a következőhöz FaultException: .

Általában csak FaultException<TDetail>a , TimeoutExceptionés CommunicationException a kivételek érdeklik az ügyfeleket és a szolgáltatásokat.

Feljegyzés

Természetesen más kivételek is előfordulnak. A váratlan kivételek közé tartoznak az olyan katasztrofális hibák, mint például System.OutOfMemoryException; az alkalmazások általában nem kapják el az ilyen módszereket.

Hiba kivételeinek fogása a helyes sorrendben

Mivel FaultException<TDetail> származik FaultException, és FaultException származik CommunicationException, fontos, hogy elfogja ezeket a kivételeket a megfelelő sorrendben. Ha például van egy próba-/fogási blokkja, amelyben először elkapja CommunicationException, az összes megadott és meghatározatlan SOAP-hiba ott lesz kezelve; az egyéni FaultException<TDetail> kivétel kezelésére szolgáló további fogási blokkok soha nem lesznek meghívva.

Ne feledje, hogy egy művelet bármilyen számú megadott hibát visszaadhat. Minden hiba egyedi típus, és külön kell kezelni.

Kivételek kezelése a csatorna bezárásakor

Az előző vitafórumok többségének az alkalmazásüzenetek feldolgozása során küldött hibákkal, azaz az ügyfél által explicit módon küldött üzenetekkel kell kapcsolatosnak kell szerepelnie, amikor az ügyfélalkalmazás műveleteket hív meg a WCF-ügyfélobjektumon.

Az újrahasznosítási folyamat során fellépő kivételeket még a helyi objektumok is feloldhatják vagy maszkolhatják. Hasonló dolog fordulhat elő WCF-ügyfélobjektumok használatakor. Amikor meghívja a műveleteket, egy létrehozott kapcsolaton keresztül küld üzeneteket. A csatorna bezárása kivételeket okozhat, ha a kapcsolat nem zárható le vagy már lezárva van, még akkor is, ha az összes művelet megfelelően visszaadott.

Az ügyfélobjektum-csatornák általában az alábbi módok egyikével vannak lezárva:

  • A WCF-ügyfélobjektum újrafeldolgozásakor.

  • Amikor az ügyfélalkalmazás hív ClientBase<TChannel>.Close.

  • Amikor az ügyfélalkalmazás hív ICommunicationObject.Close.

  • Amikor az ügyfélalkalmazás olyan műveletet hív meg, amely egy munkamenet megszakítási művelete.

A csatorna bezárása minden esetben arra utasítja a csatornát, hogy kezdje el bezárni azokat a mögöttes csatornákat, amelyek üzeneteket küldhetnek az alkalmazás szintjén az összetett funkciók támogatásához. Ha például egy szerződés munkameneteket igényel, kötési kísérlet egy munkamenet létrehozására úgy, hogy üzeneteket cserél a szolgáltatáscsatornával, amíg létre nem jön egy munkamenet. A csatorna bezárásakor a mögöttes munkamenetcsatorna értesíti a szolgáltatást, hogy a munkamenet le van állítva. Ebben az esetben, ha a csatorna már megszakadt, bezárult, vagy egyébként használhatatlan (például hálózati kábel leválasztásakor), az ügyfélcsatorna nem tudja értesíteni a szolgáltatáscsatornát arról, hogy a munkamenet leállt, és kivételt eredményezhet.

Szükség esetén megszakítja a csatornát

Mivel a csatorna bezárása kivételeket is okozhat, ezért a hibakivüldő kivételek helyes sorrendben történő elfogása mellett fontos megszakítani a híváshoz használt csatornát a fogási blokkban.

Ha a hiba egy adott műveletre vonatkozó hibainformációkat ad át, és továbbra is lehetséges, hogy mások is használhatják, nincs szükség a csatorna megszakítására (bár ezek az esetek ritkák). Minden más esetben javasoljuk, hogy megszakítsa a csatornát. Az összes pontot bemutató minta esetében lásd a várt kivételeket.

Az alábbi példakód bemutatja, hogyan kezelhetők a SOAP-hibák kivételei egy alapszintű ügyfélalkalmazásban, beleértve a deklarált hibát és a be nem jelentett hibát.

Feljegyzés

Ez a mintakód nem használja a szerkezetet using . Mivel a bezárt csatornák kivételeket okozhatnak, javasoljuk, hogy az alkalmazások először hozzon létre EGY WCF-ügyfelet, majd nyissa meg, használja és zárja be a WCF-ügyfelet ugyanabban a kipróbálási blokkban. További részletekért tekintse meg a WCF-ügyfél áttekintését , valamint a WCF-ügyfélerőforrások kiadásához a Bezárás és megszakítás használata lehetőséget.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    SampleServiceClient wcfClient = new SampleServiceClient();
    try
    {
      // Making calls.
      Console.WriteLine("Enter the greeting to send: ");
      string greeting = Console.ReadLine();
      Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));

      Console.WriteLine("Press ENTER to exit:");
      Console.ReadLine();

      // Done with service.
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException<GreetingFault> greetingFault)
    {
      Console.WriteLine(greetingFault.Detail.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException unknownFault)
    {
      Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
      Console.ReadLine();
      wcfClient.Abort();
    }
  }
}

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
    Public Shared Sub Main()
        ' Picks up configuration from the config file.
        Dim wcfClient As New SampleServiceClient()
        Try
            ' Making calls.
            Console.WriteLine("Enter the greeting to send: ")
            Dim greeting As String = Console.ReadLine()
            Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

            Console.WriteLine("Press ENTER to exit:")
            Console.ReadLine()

            ' Done with service. 
            wcfClient.Close()
            Console.WriteLine("Done!")
        Catch timeProblem As TimeoutException
            Console.WriteLine("The service operation timed out. " & timeProblem.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch greetingFault As FaultException(Of GreetingFault)
            Console.WriteLine(greetingFault.Detail.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch unknownFault As FaultException
            Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch commProblem As CommunicationException
            Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
            Console.ReadLine()
            wcfClient.Abort()
        End Try
    End Sub
End Class

Lásd még