Sessies gebruiken
In WCF-toepassingen (Windows Communication Foundation) correleert een sessie een groep berichten in een gesprek. WCF-sessies verschillen van het sessieobject dat beschikbaar is in ASP.NET toepassingen, ondersteunen verschillende gedragingen en worden op verschillende manieren beheerd. In dit onderwerp worden de functies beschreven die sessies inschakelen in WCF-toepassingen en hoe u deze kunt gebruiken.
Sessies in Windows Communication Foundation-toepassingen
Wanneer een servicecontract aangeeft dat er een sessie nodig is, moet dat contract aangeven dat alle oproepen (dat wil zeggen de onderliggende berichtenuitwisselingen die ondersteuning bieden voor de oproepen) deel moeten uitmaken van hetzelfde gesprek. Als een contract aangeeft dat sessies zijn toegestaan, maar geen sessie vereist, kunnen clients verbinding maken en een sessie tot stand brengen of geen sessie tot stand brengen. Als de sessie eindigt en een bericht via hetzelfde kanaal wordt verzonden, wordt er een uitzondering gegenereerd.
WCF-sessies hebben de volgende belangrijke conceptuele functies:
Ze worden expliciet geïnitieerd en beëindigd door de aanroepende toepassing (de WCF-client).
Berichten die tijdens een sessie worden bezorgd, worden verwerkt in de volgorde waarin ze worden ontvangen.
Sessies correleren een groep berichten in een gesprek. Er zijn verschillende soorten correlatie mogelijk. Eén sessiegebaseerd kanaal kan bijvoorbeeld berichten correleren op basis van een gedeelde netwerkverbinding, terwijl een ander sessiekanaal berichten kan correleren op basis van een gedeelde tag in de berichttekst. De functies die kunnen worden afgeleid van de sessie, zijn afhankelijk van de aard van de correlatie.
Er is geen algemeen gegevensarchief gekoppeld aan een WCF-sessie.
Als u bekend bent met de System.Web.SessionState.HttpSessionState klasse in ASP.NET toepassingen en de functionaliteit die deze biedt, ziet u mogelijk de volgende verschillen tussen dat soort sessies en WCF-sessies:
ASP.NET sessies worden altijd door de server geïnitieerd.
ASP.NET sessies impliciet ongeordeerd zijn.
ASP.NET sessies bieden een algemeen mechanisme voor gegevensopslag voor aanvragen.
In dit onderwerp wordt het volgende beschreven:
Het standaardgedrag voor uitvoering bij het gebruik van sessiebindingen in de servicemodellaag.
De typen functies die de WCF-sessiegebaseerde, door het systeem geleverde bindingen bieden.
Een contract maken dat een sessievereiste declareert.
Het maken en beëindigen van de sessie en de relatie van de sessie met het service-exemplaar begrijpen en beheren.
Standaarduitvoeringsgedrag met behulp van sessies
Een binding die een sessie probeert te initiëren, wordt een op een sessie gebaseerde binding genoemd. Servicecontracten geven aan dat ze op sessies gebaseerde bindingen vereisen, toestaan of weigeren door de ServiceContractAttribute.SessionMode eigenschap op de interface van het servicecontract (of de klasse) in te stellen op een van de System.ServiceModel.SessionMode opsommingswaarden. De waarde van deze eigenschap is Allowedstandaard, wat betekent dat als een client gebruikmaakt van een sessiegebaseerde binding met een WCF-service-implementatie, de service de geleverde sessie tot stand brengt en gebruikt.
Wanneer een WCF-service een clientsessie accepteert, zijn de volgende functies standaard ingeschakeld:
Alle aanroepen tussen een WCF-clientobject worden verwerkt door hetzelfde service-exemplaar.
Verschillende op sessies gebaseerde bindingen bieden aanvullende functies.
Door het systeem geleverde sessietypen
Een binding op basis van een sessie ondersteunt de standaardkoppeling van een service-exemplaar met een bepaalde sessie. Verschillende sessiebindingen bieden echter ondersteuning voor verschillende functies, naast het inschakelen van het eerder beschreven sessiebeheer.
WCF biedt de volgende typen toepassingsgedrag op basis van sessies:
Het System.ServiceModel.Channels.SecurityBindingElement biedt ondersteuning voor op beveiliging gebaseerde sessies, waarbij beide uiteinden van de communicatie een specifiek beveiligd gesprek hebben afgesproken. Zie Services beveiligen voor meer informatie. De binding, die ondersteuning voor zowel beveiligingssessies als betrouwbare sessies bevat, gebruikt standaard System.ServiceModel.WSHttpBinding alleen een beveiligde sessie die berichten versleutelt en digitaal ondertekent.
De System.ServiceModel.NetTcpBinding binding ondersteunt TCP/IP-sessies om ervoor te zorgen dat alle berichten worden gecorreleerd door de verbinding op socketniveau.
Het System.ServiceModel.Channels.ReliableSessionBindingElement element, dat de WS-ReliableMessaging-specificatie implementeert, biedt ondersteuning voor betrouwbare sessies waarin berichten op volgorde en precies één keer kunnen worden geleverd, zodat berichten worden ontvangen, zelfs wanneer berichten tijdens het gesprek over meerdere knooppunten worden verzonden. Zie Reliable Sessions voor meer informatie.
De System.ServiceModel.NetMsmqBinding binding biedt MSMQ-datagramsessies. Zie Wachtrijen in WCF voor meer informatie.
Als u de SessionMode eigenschap instelt, wordt niet het type sessie opgegeven dat het contract nodig heeft, maar alleen dat hiervoor een sessie is vereist.
Een contract maken waarvoor een sessie is vereist
Als u een contract maakt waarvoor een sessie is vereist, wordt aangegeven dat de groep bewerkingen die het servicecontract declareert, allemaal binnen dezelfde sessie moeten worden uitgevoerd en dat berichten in volgorde moeten worden afgeleverd. Als u het sessieondersteuningsniveau wilt bevestigen dat een servicecontract vereist, stelt u de ServiceContractAttribute.SessionMode eigenschap in uw servicecontractinterface of klasse in op de waarde van de System.ServiceModel.SessionMode opsomming om op te geven of het contract:
Vereist een sessie.
Hiermee kan een client een sessie tot stand brengen.
Verbiedt een sessie.
Als u de SessionMode eigenschap instelt, geeft u echter niet het type sessiegedrag op dat het contract vereist. Het geeft WCF opdracht om tijdens runtime te bevestigen dat de geconfigureerde binding (die het communicatiekanaal maakt) voor de service wel, niet of kan een sessie tot stand brengen bij het implementeren van een service. Opnieuw kan de binding voldoen aan die vereiste met elk type sessiegedrag dat het kiest: beveiliging, transport, betrouwbaar of een combinatie. Het exacte gedrag is afhankelijk van de System.ServiceModel.SessionMode geselecteerde waarde. Als de geconfigureerde binding van de service niet voldoet aan de waarde van SessionMode, wordt er een uitzondering gegenereerd. Bindingen en de kanalen die ze maken die ondersteuningssessies ondersteunen, worden op sessiebasis gezegd.
Het volgende servicecontract geeft aan dat alle bewerkingen in de ICalculatorSession
sessie moeten worden uitgewisseld. Geen van de bewerkingen retourneert een waarde aan de aanroeper, behalve de Equals
methode. De Equals
methode gebruikt echter geen parameters en kan daarom alleen een niet-nulwaarde retourneren binnen een sessie waarin gegevens al zijn doorgegeven aan de andere bewerkingen. Voor dit contract is een sessie vereist om goed te functioneren. Zonder een sessie die is gekoppeld aan een specifieke client, kan het service-exemplaar niet weten welke eerdere gegevens deze client heeft verzonden.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract(IsOneWay = true)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true)]
void DivideBy(double n);
[OperationContract]
double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession
<OperationContract(IsOneWay:=True)> _
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub DivideBy(ByVal n As Double)
<OperationContract()> _
Function Equal() As Double
End Interface
Als een service een sessie toestaat, wordt er een sessie tot stand gebracht en gebruikt als de client er een initieert; anders wordt er geen sessie tot stand gebracht.
Sessies en service-exemplaren
Als u het standaardgedrag voor instancing in WCF gebruikt, worden alle aanroepen tussen een WCF-clientobject verwerkt door hetzelfde service-exemplaar. Daarom kunt u op toepassingsniveau een sessie beschouwen als het inschakelen van toepassingsgedrag dat vergelijkbaar is met het gedrag van lokale aanroepen. Wanneer u bijvoorbeeld een lokaal object maakt:
Een constructor wordt aangeroepen.
Alle volgende aanroepen naar de WCF-clientobjectverwijzing worden verwerkt door hetzelfde objectexemplaren.
Een destructor wordt aangeroepen wanneer de objectverwijzing wordt vernietigd.
Sessies maken een vergelijkbaar gedrag mogelijk tussen clients en services zolang het standaardgedrag van het service-exemplaar wordt gebruikt. Als een servicecontract sessies vereist of ondersteunt, kunnen een of meer contractbewerkingen worden gemarkeerd als initiëren of beëindigen van een sessie door de IsInitiating en IsTerminating eigenschappen in te stellen.
Initiërende bewerkingen zijn bewerkingen die moeten worden aangeroepen als de eerste bewerking van een nieuwe sessie. Niet-initiërende bewerkingen kunnen alleen worden aangeroepen nadat ten minste één initiërende bewerking is aangeroepen. U kunt daarom een soort sessieconstructor voor uw service maken door initiërende bewerkingen te declareren die zijn ontworpen om invoer te nemen van clients die geschikt zijn voor het begin van het service-exemplaar. (De status is echter gekoppeld aan de sessie en niet aan het serviceobject.)
Afsluitbewerkingen zijn daarentegen de bewerkingen die moeten worden aangeroepen als het laatste bericht in een bestaande sessie. In het standaardscenario recyclet WCF het serviceobject en de bijbehorende context na de sessie waarmee de service is gekoppeld, is gesloten. U kunt daarom een soort destructor maken door afsluitbewerkingen te declareren die zijn ontworpen om een functie uit te voeren die geschikt is voor het einde van het service-exemplaar.
Notitie
Hoewel het standaardgedrag lijkt op lokale constructors en destructors, is het slechts een gelijkenis. Elke WCF-servicebewerking kan een initiërende of afsluitbewerking zijn, of beide tegelijk. In het standaardscenario kunnen initiërende bewerkingen bovendien een willekeurig aantal keren in elke volgorde worden aangeroepen; er worden geen extra sessies gemaakt zodra de sessie tot stand is gebracht en gekoppeld aan een exemplaar, tenzij u expliciet de levensduur van het service-exemplaar beheert (door het System.ServiceModel.InstanceContext object te bewerken). Ten slotte is de status gekoppeld aan de sessie en niet aan het serviceobject.
Het contract dat in het vorige voorbeeld wordt gebruikt, ICalculatorSession
vereist bijvoorbeeld dat het WCF-clientobject eerst de Clear
bewerking aanroept voorafgaand aan een andere bewerking en dat de sessie met dit WCF-clientobject moet worden beëindigd wanneer de Equals
bewerking wordt aangeroepen. In het volgende codevoorbeeld ziet u een contract waarmee deze vereisten worden afgedwongen. Clear
moet eerst worden aangeroepen om een sessie te starten en die sessie eindigt wanneer Equals
deze wordt aangeroepen.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
[OperationContract(IsOneWay=true, IsInitiating=true, IsTerminating=false)]
void Clear();
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void AddTo(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
void DivideBy(double n);
[OperationContract(IsInitiating = false, IsTerminating = true)]
double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession
<OperationContract(IsOneWay:=True, IsInitiating:=True, IsTerminating:=False)> _
Sub Clear()
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
Sub DivideBy(ByVal n As Double)
<OperationContract(IsInitiating:=False, IsTerminating:=True)> _
Function Equal() As Double
End Interface
Services starten geen sessies met clients. In WCF-clienttoepassingen bestaat er een directe relatie tussen de levensduur van het sessiekanaal en de levensduur van de sessie zelf. Als zodanig maken clients nieuwe sessies door nieuwe op sessies gebaseerde kanalen te maken en bestaande sessies te afbreken door op sessies gebaseerde kanalen probleemloos te sluiten. Een client start een sessie met een service-eindpunt door een van de volgende aan te roepen:
ICommunicationObject.Open op het kanaal geretourneerd door een aanroep naar ChannelFactory<TChannel>.CreateChannel.
ClientBase<TChannel>.Openop het WCF-clientobject dat is gegenereerd door het Hulpprogramma voor metagegevens van ServiceModel (Svcutil.exe).
Een initiërende bewerking voor een van beide typen WCF-clientobjecten (standaard worden alle bewerkingen gestart). Wanneer de eerste bewerking wordt aangeroepen, wordt het kanaal automatisch geopend met het WCF-clientobject en wordt een sessie gestart.
Normaal gesproken beëindigt een client een sessie met een service-eindpunt door een van de volgende aan te roepen:
ICommunicationObject.Close op het kanaal geretourneerd door een aanroep naar ChannelFactory<TChannel>.CreateChannel.
ClientBase<TChannel>.Close op het WCF-clientobject dat is gegenereerd door Svcutil.exe.
Een afsluitbewerking voor een van beide typen WCF-clientobjecten (standaard worden er geen bewerkingen beëindigd; het contract moet expliciet een afsluitbewerking opgeven). Wanneer de eerste bewerking wordt aangeroepen, wordt het kanaal automatisch geopend met het WCF-clientobject en wordt een sessie gestart.
Zie Voor voorbeelden: Een service maken waarvoor sessies zijn vereist, evenals de standaardvoorbeelden voor servicegedrag en instancing.
Zie Toegang tot services met behulp van een WCF-client voor meer informatie over clients en sessies.
Sessies communiceren met InstanceContext Instellingen
Er is een interactie tussen de SessionMode opsomming in een contract en de ServiceBehaviorAttribute.InstanceContextMode eigenschap, waarmee de koppeling tussen kanalen en specifieke serviceobjecten wordt bepaald. Zie Sessies, Instancing en Gelijktijdigheid voor meer informatie.
InstanceContext-objecten delen
U kunt ook bepalen welk kanaal of welk gesprek op basis van een sessie is gekoppeld aan welk InstanceContext object door die koppeling zelf uit te voeren.
Sessies en streaming
Wanneer u een grote hoeveelheid gegevens hebt die moet worden overgedragen, is de streamingoverdrachtmodus in WCF een haalbaar alternatief voor het standaardgedrag van het bufferen en verwerken van berichten in het geheugen in zijn geheel. Mogelijk krijgt u onverwacht gedrag bij het streamen van oproepen met een binding op basis van een sessie. Alle streaming-aanroepen worden gedaan via één kanaal (het datagramkanaal) dat geen ondersteuning biedt voor sessies, zelfs niet als de binding die wordt gebruikt, is geconfigureerd voor het gebruik van sessies. Als meerdere clients streaming-aanroepen naar hetzelfde serviceobject uitvoeren via een sessiebinding en de gelijktijdigheidsmodus van het serviceobject is ingesteld op enkel en de contextmodus van het exemplaar is ingesteld PerSession
op, moeten alle aanroepen via het datagramkanaal gaan en dus slechts één aanroep tegelijk worden verwerkt. Een of meer clients kunnen dan een time-out uitvoeren. U kunt dit probleem omzeilen door het serviceobject InstanceContextMode
in te PerCall
stellen op meerdere objecten of gelijktijdigheid.
Notitie
MaxConcurrentSessions hebben in dit geval geen effect omdat er slechts één sessie beschikbaar is.