Delen via


HttpCookieSession

Het httpCookieSession-voorbeeld laat zien hoe u een aangepast protocolkanaal bouwt voor het gebruik van HTTP-cookies voor sessiebeheer. Dit kanaal maakt communicatie mogelijk tussen WCF-services (Windows Communication Foundation) en ASMX-clients of tussen WCF-clients en ASMX-services.

Wanneer een client een webmethode aanroept in een ASMX-webservice die op een sessie is gebaseerd, doet de ASP.NET-engine het volgende:

  • Hiermee wordt een unieke id (sessie-id) gegenereerd.

  • Hiermee genereert u het sessieobject en koppelt u het aan de unieke id.

  • Voegt de unieke id toe aan een Set-Cookie HTTP-antwoordheader en verzendt deze naar de client.

  • Identificeert de client op volgende aanroepen op basis van de sessie-id die naar de client wordt verzonden.

De client bevat deze sessie-id in de volgende aanvragen voor de server. De server gebruikt de sessie-id van de client om het juiste sessieobject voor de huidige HTTP-context te laden.

HttpCookieSession-kanaalberichtuitwisselingspatroon

Dit voorbeeld maakt sessies mogelijk voor ASMX-achtige scenario's. Onderaan onze kanaalstack hebben we het HTTP-transport dat IRequestChannel en IReplyChannel ondersteunt. Het is de taak van het kanaal om sessies te bieden aan de hogere niveaus van de kanaalstapel. In het voorbeeld worden twee kanalen geïmplementeerd, (IRequestSessionChannel en IReplySessionChannel) die ondersteuning bieden voor sessies.

Servicekanaal

Het voorbeeld biedt een servicekanaal in de HttpCookieReplySessionChannelListener klasse. Deze klasse implementeert de IChannelListener interface en converteert het IReplyChannel kanaal van lager in de kanaalstack naar een IReplySessionChannel. Dit proces kan worden onderverdeeld in de volgende onderdelen:

  • Wanneer de kanaalluisteraar wordt geopend, accepteert deze een intern kanaal van de interne luisteraar. Omdat de binnenste listener een datagramlistener is en de levensduur van een geaccepteerd kanaal wordt losgekoppeld van de levensduur van de listener, kunnen we de binnenste listener sluiten en alleen het binnenste kanaal vasthouden

                this.innerChannelListener.Open(timeoutHelper.RemainingTime());
    this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime());
    this.innerChannel.Open(timeoutHelper.RemainingTime());
    this.innerChannelListener.Close(timeoutHelper.RemainingTime());
    
  • Wanneer het geopende proces is voltooid, stellen we een berichtenlus in om berichten van het binnenste kanaal te ontvangen.

    IAsyncResult result = BeginInnerReceiveRequest();
    if (result != null && result.CompletedSynchronously)
    {
       // do not block the user thread
       this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback);
       ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result);
    }
    
  • Wanneer er een bericht binnenkomt, onderzoekt het servicekanaal de sessie-identificator en demultiplexen naar het juiste sessiekanaal. De kanaallistener onderhoudt een woordenlijst waarmee de sessie-id's worden toegewezen aan de sessiekanaalexemplaren.

    Dictionary<string, IReplySessionChannel> channelMapping;
    

De HttpCookieReplySessionChannel klasse implementeert IReplySessionChannel. Hogere niveaus van de kanaalstack roepen de ReceiveRequest methode aan om aanvragen voor deze sessie te lezen. Elk sessiekanaal heeft een privéberichtwachtrij die wordt gevuld door het servicekanaal.

InputQueue<RequestContext> requestQueue;

Als iemand de ReceiveRequest methode aanroept en er geen berichten in de berichtenwachtrij staan, wacht het kanaal een specifieke tijdsduur voordat het zichzelf afsluit. Hiermee worden de sessiekanalen opgeschoond die zijn gemaakt voor niet-WCF-clients.

We gebruiken de channelMapping om de ReplySessionChannels te volgen, en we sluiten onze onderliggende innerChannel structuren pas nadat alle geaccepteerde kanalen zijn gesloten. Deze manier HttpCookieReplySessionChannel kan bestaan na de levensduur van HttpCookieReplySessionChannelListener. We hoeven ons ook geen zorgen te maken dat de listener wordt opgehaald door de garbage collector omdat de geaccepteerde kanalen via de OnClosed callback een verwijzing naar hun listener behouden.

Clientkanaal

Het bijbehorende clientkanaal bevindt zich in de HttpCookieSessionChannelFactory klasse. Tijdens het maken van het kanaal verpakt de kanaalfactory het binnenste aanvraagkanaal met een HttpCookieRequestSessionChannel. De HttpCookieRequestSessionChannel klasse stuurt de aanroepen door naar het onderliggende aanvraagkanaal. Wanneer de client de proxy sluit, HttpCookieRequestSessionChannel verzendt u een bericht naar de service die aangeeft dat het kanaal wordt gesloten. Daarom kan de servicekanaalstack het sessiekanaal dat wordt gebruikt, probleemloos afsluiten.

Bindings- en bindingselement

Nadat u de service- en clientkanalen hebt gemaakt, is de volgende stap het integreren ervan in de WCF-runtime. Kanalen worden beschikbaar gesteld aan WCF via bindingen en bindingselementen. Een binding bestaat uit een of meer bindingselementen. WCF biedt verschillende door het systeem gedefinieerde bindingen; Bijvoorbeeld BasicHttpBinding of WSHttpBinding. De HttpCookieSessionBindingElement klasse bevat de implementatie voor het bindingselement. Het overschrijft de methoden voor het maken van de kanaallistener en kanaalfactory om de benodigde kanaallistener- of kanaalfactory-instantiëringen uit te voeren.

In het voorbeeld worden beleidsverklaringen gebruikt voor de servicebeschrijving. Hierdoor kan de steekproef zijn kanaalvereisten publiceren aan andere clients die de service kunnen gebruiken. Met dit bindingselement worden bijvoorbeeld beleidsverklaringen gepubliceerd om potentiële clients te laten weten dat het sessies ondersteunt. Omdat het voorbeeld de ExchangeTerminateMessage eigenschap inschakelt in de configuratie van het bindingselement, worden de benodigde asserties toegevoegd om aan te geven dat de service ondersteuning biedt voor een extra actie voor het uitwisselen van berichten om het sessiegesprek te beëindigen. Clients kunnen deze actie vervolgens gebruiken. De volgende WSDL-code toont de beleidsverklaringen die zijn gemaakt op basis van de HttpCookieSessionBindingElement.

<wsp:Policy wsu:Id="HttpCookieSessionBinding_IWcfCookieSessionService_policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<wspe:Utf816FFFECharacterEncoding xmlns:wspe="http://schemas.xmlsoap.org/ws/2004/09/policy/encoding"/>
<mhsc:httpSessionCookie xmlns:mhsc="http://samples.microsoft.com/wcf/mhsc/policy"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>

De HttpCookieSessionBinding klasse is een door het systeem geleverde binding die gebruikmaakt van het eerder beschreven bindingselement.

Het kanaal toevoegen aan het configuratiesysteem

Het voorbeeld biedt twee klassen die het voorbeeldkanaal beschikbaar maken via configuratie. De eerste is een BindingElementExtensionElement voor de HttpCookieSessionBindingElement. Het grootste deel van de implementatie wordt gedelegeerd aan de HttpCookieSessionBindingConfigurationElement, die is afgeleid van StandardBindingElement. De HttpCookieSessionBindingConfigurationElement heeft eigenschappen die overeenkomen met de eigenschappen op HttpCookieSessionBindingElement.

Sectie bindende elementextensie

De sectie HttpCookieSessionBindingElementSection is een BindingElementExtensionElement die HttpCookieSessionBindingElement blootstelt aan het configuratiesysteem. Met een paar overrides worden de naam van de configuratiesectie, het type van het bindingselement en hoe het bindingselement te creëren gedefinieerd. Vervolgens kunnen we de extensiesectie als volgt registreren in een configuratiebestand:

<configuration>
    <system.serviceModel>
      <extensions>
        <bindingElementExtensions>
          <add name="httpCookieSession"
               type=
"Microsoft.ServiceModel.Samples.HttpCookieSessionBindingElementElement,
                    HttpCookieSessionExtension, Version=1.0.0.0,
                    Culture=neutral, PublicKeyToken=null"/>
        </bindingElementExtensions >
      </extensions>

      <bindings>
      <customBinding>
        <binding name="allowCookiesBinding">
          <textMessageEncoding messageVersion="Soap11WSAddressing10" />
          <httpCookieSession sessionTimeout="10" exchangeTerminateMessage="true" />
          <httpTransport allowCookies="true" />
        </binding>
      </customBinding>
      </bindings>
    </system.serviceModel>
</configuration>

Code testen

Testcode voor het gebruik van dit voorbeeldtransport is beschikbaar in de mappen Client en Service. Het bestaat uit twee tests: één test gebruikt een binding waarbij allowCookies is ingesteld op true bij de client. Met de tweede test kunt u expliciet beëindigen door het beëindigingsbericht uit te wisselen van de binding.

Wanneer u het voorbeeld uitvoert, ziet u de volgende uitvoer:

Simple binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Smart binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3

Press <ENTER> to terminate client.

Het voorbeeld instellen, compileren en uitvoeren

  1. Installeer ASP.NET 4.0 met de volgende opdracht.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Zorg ervoor dat u de One-Time Setup Procedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.

  3. Volg de instructies in Het bouwen van de Windows Communication Foundation-voorbeelden om de oplossing te bouwen.

  4. Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Windows Communication Foundation-voorbeelden uitvoeren.