HttpCookieSession

Im HttpCookieSession-Beispiel wird das Erstellen eines benutzerdefinierten Protokollkanals für die Verwendung von HTTP-Cookies für die Sitzungsverwaltung veranschaulicht. Dieser Kanal ermöglicht die Kommunikation zwischen WCF-Diensten (Windows Communication Foundation) und ASMX-Clients oder zwischen WCF-Clients und ASMX-Diensten.

Wenn ein Client eine Webmethode in einem sitzungsbasierten ASMX-Webdienst aufruft, führt die ASP.NET-Engine Folgendes aus:

  • Generiert eine eindeutige ID (Sitzungs-ID).

  • Generiert das Sitzungsobjekt und ordnet es der eindeutigen ID zu.

  • Fügt die eindeutige ID dem HTTP-Antwortheader Set-Cookie hinzu und sendet diesen an den Client.

  • Identifiziert den Client in nachfolgenden Aufrufen auf Grundlage der an ihn gesendeten Sitzungs-ID.

Der Client schließt diese Sitzungs-ID in nachfolgenden Anforderungen an den Server ein. Der Server lädt mithilfe der Sitzungs-ID vom Client das entsprechende Sitzungsobjekt für den aktuellen HTTP-Kontext.

HttpCookieSession-Nachrichtenaustauschmuster für Kanal

In diesem Beispiel werden Sitzungen für ASMX-ähnliche Szenarios aktiviert. Unten im Kanalstapel befindet sich der HTTP-Transport, der IRequestChannel und IReplyChannel unterstützt. Der Kanal stellt Sitzungen für die höheren Ebenen des Kanalstapels bereit. Im Beispiel werden zwei Kanäle implementiert, die Sitzungen unterstützen (IRequestSessionChannel und IReplySessionChannel).

Dienstkanal

Im Beispiel wird ein Dienstkanal in der HttpCookieReplySessionChannelListener-Klasse bereitgestellt. Diese Klasse implementiert die IChannelListener-Schnittstelle und konvertiert den IReplyChannel-Kanal weiter unten im Kanalstapel in IReplySessionChannel. Dieser Prozess kann folgendermaßen unterteilt werden:

  • Wenn der Kanallistener geöffnet wird, akzeptiert er einen inneren Kanal vom inneren Listener. Da es sich bei dem inneren Listener um einen Datagrammlistener handelt und die Lebensdauer eines akzeptierten Kanals unabhängig von der Lebensdauer des Listeners ist, kann der innere Listener geschlossen und nur der innere Kanal beibehalten werden.

                this.innerChannelListener.Open(timeoutHelper.RemainingTime());
    this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime());
    this.innerChannel.Open(timeoutHelper.RemainingTime());
    this.innerChannelListener.Close(timeoutHelper.RemainingTime());
    
  • Wenn der Prozess zum Öffnen abgeschlossen ist, wird eine Nachrichtenschleife zum Empfangen von Nachrichten vom inneren Kanal eingerichtet.

    IAsyncResult result = BeginInnerReceiveRequest();
    if (result != null && result.CompletedSynchronously)
    {
       // do not block the user thread
       this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback);
       ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result);
    }
    
  • Wenn eine Nachricht eingeht, prüft der Dienstkanal die Sitzungs-ID und führt ein De-Multiplexing für den entsprechenden Sitzungskanal durch. Der Kanallistener verwaltet ein Wörterbuch, das die Sitzungs-IDs den Sitzungskanalinstanzen zuordnet.

    Dictionary<string, IReplySessionChannel> channelMapping;
    

Die HttpCookieReplySessionChannel-Klasse implementiert IReplySessionChannel. In höheren Ebenen des Kanalstapels wird die ReceiveRequest-Methode aufgerufen, um Anforderungen für diese Sitzung zu lesen. Jeder Sitzungskanal verfügt über eine private Meldungswarteschlange, die vom Dienstkanal aufgefüllt wird.

InputQueue<RequestContext> requestQueue;

Wenn die ReceiveRequest-Methode aufgerufen wird und sich keine Meldungen in der Meldungswarteschlange befinden, wartet der Kanal für einen angegebenen Zeitraum und beendet sich dann selbst. So werden die für Nicht-WCF-Clients erstellten Sitzungskanäle bereinigt.

Mit channelMapping wird ReplySessionChannels nachverfolgt. Außerdem wird der zugrunde liegende innerChannel erst geschlossen, wenn alle akzeptierten Kanäle geschlossen wurden. So kann HttpCookieReplySessionChannel über die Lebensdauer von HttpCookieReplySessionChannelListener hinaus vorhanden sein. Außerdem besteht nicht die Gefahr, dass der Listener durch die Garbage Collection entfernt wird, da die akzeptierten Kanäle über den OnClosed-Rückruf einen Verweis auf den Listener beibehalten.

Clientkanal

Der entsprechende Clientkanal befindet sich in der HttpCookieSessionChannelFactory-Klasse. Bei der Kanalerstellung schließt die Kanalfactory den inneren Anforderungskanal mit einem HttpCookieRequestSessionChannel ein. Die HttpCookieRequestSessionChannel-Klasse leitet die Aufrufe des zugrunde liegenden Anforderungskanals weiter. Wenn der Client den Proxy schließt, sendet HttpCookieRequestSessionChannel eine Meldung an den Dienst, mit der angegeben wird, dass der Kanal geschlossen wird. So kann der Dienstkanalstapel den verwendeten Sitzungskanal ordnungsgemäß beenden.

Bindung und Bindungselement

Nach dem Erstellen der Dienst- und Clientkanäle ist der nächste Schritt das Integrieren der Kanäle in der WCF-Laufzeit. Kanäle werden durch Bindungen und Bindungselemente für WCF verfügbar gemacht. Eine Bindung besteht aus einem oder mehreren Bindungselementen. WCF stellt mehrere systemdefinierte Bindungen bereit, beispielsweise BasicHttpBinding und WSHttpBinding. Die HttpCookieSessionBindingElement-Klasse enthält die Implementierung des Bindungselements. Sie überschreibt die Methoden zur Kanallistener- und Kanalfactoryerstellung, um die erforderlichen Instanziierungen des Kanallisteners und der Kanalfactory auszuführen.

Im Beispiel werden Richtlinienassertionen für die Dienstbeschreibung verwendet. So können im Beispiel die Kanalanforderungen für andere Clients veröffentlicht werden, die den Dienst verwenden können. Dieses Bindungselement veröffentlicht beispielsweise Richtlinienassertionen, damit potenzielle Clients wissen, dass Sitzungen unterstützt werden. Da im Beispiel die ExchangeTerminateMessage-Eigenschaft in der Bindungselementkonfiguration aktiviert wird, werden die erforderlichen Assertionen hinzugefügt, um zu zeigen, dass der Dienst eine zusätzliche Meldungsaustauschaktion zum Beenden der Sitzungskommunikation unterstützt. Clients können diese Aktion dann verwenden. Im folgenden WSDL-Code werden die aus HttpCookieSessionBindingElement erstellten Richtlinienassertionen veranschaulicht.

<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>

Die HttpCookieSessionBinding-Klasse ist eine vom System bereitgestellte Bindung, die das zuvor beschriebene Bindungselement verwendet.

Hinzufügen des Kanals zum Konfigurationssystem

Im Beispiel werden zwei Klassen bereitgestellt, die den Beispielkanal durch Konfiguration verfügbar machen. Die erste ist ein BindingElementExtensionElement für das HttpCookieSessionBindingElement. Dem HttpCookieSessionBindingConfigurationElement, das sich von StandardBindingElement herleitet, wird der Großteil der Implementierung übertragen. HttpCookieSessionBindingConfigurationElement verfügt über Eigenschaften, die den Eigenschaften von HttpCookieSessionBindingElement entsprechen.

Abschnitt für Bindungselementerweiterungen

Der Abschnitt HttpCookieSessionBindingElementSection ist ein BindingElementExtensionElement, das die HttpCookieSessionBindingElement für das Konfigurationssystem verfügbar macht. Mit wenigen Überschreibungen werden der Konfigurationsabschnittsname, der Typ des Bindungselements und das Erstellen des Bindungselements definiert. Danach kann der Erweiterungsabschnitt wie folgt in einer Konfigurationsdatei registriert werden:

<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>

Testcode

Testcode für die Verwendung dieses Beispieltransports ist in den Client- und Dienstverzeichnissen verfügbar. Dieser besteht aus zwei Tests. In einem Test wird eine Bindung verwendet, wobei allowCookies auf dem Client auf true festgelegt ist. Im zweiten Test wird das explizite Herunterfahren (mit abschließenden Meldungsaustausch) für die Bindung aktiviert.

Wenn Sie das Beispiel ausführen, sollten Sie folgende Ausgabe erhalten:

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.

So können Sie das Beispiel einrichten, erstellen und ausführen

  1. Installieren Sie ASP.NET 4.0 mithilfe des folgenden Befehls.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Stellen Sie sicher, dass Sie die Beispiele zum einmaligen Setupverfahren für Windows Communication Foundation ausgeführt haben.

  3. Befolgen Sie zum Erstellen der Projektmappe die Anweisungen unter Erstellen der Windows Communication Foundation-Beispiele.

  4. Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.