2012-12-06 14 views
8

Ho servizio WCF consumato dal cliente AJAX usando SOAP 1.2Perché InstanceContextMode.PerSession si comporta come PerCall quando si utilizza wsHttpBinding?

web.config:

<endpoint address="" binding="wsHttpBinding" 
contract="WcfService1.IService1" bindingConfiguration="wsHttpBin"> 

<wsHttpBinding> 
    <binding name="wsHttpBin"> 
    <security mode="None"/>   
    </binding> 
</wsHttpBinding> 

Da quello che ho read, devo usare <security mode="None"/> dal momento che un servizio di vista con “wsHttpBinding” vincolante implementa le specifiche della famiglia di servizi Web WS-Security di WS- *. Poiché l'associazione utilizza la sicurezza, la richiesta verrà rifiutata poiché AJAX non supporta il contesto di sicurezza.

mio WCF comportamento del servizio è definita con InstanceContextMode.PerSession:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
       InstanceContextMode = InstanceContextMode.PerSession)] 

ma quando ho consumare, si comportano servizio come PerCall e ogni chiamata avvia una nuova istanza WCF invece di utilizzare l'istanza corrente.

Perché InstanceContextMode.PerSession si comporta come PerCall quando si utilizza wsHttpBinding?

Cosa posso fare?

+0

possibile duplicato: http://stackoverflow.com/questions/4767102/wcf-sessions-with-a-wshttpbinding-and-without-windows-security – ErnieL

+0

@ErnieL Grazie ma utilizzando non è un'opzione per me dal momento che non funzionerà con il mio client AJAX. –

+0

Da solo wsHttpBinding non supporta le sessioni. – ErnieL

risposta

3

Le sessioni, se utilizzate su HTTP, sono supportate solo da WCF quando si utilizzano sessioni di sicurezza o sessioni affidabili. Se non puoi usare entrambi, devi implementare un meccanismo di sessione da solo. Se controlli sia il lato client che il lato server, sarebbe abbastanza facile farlo. Ecco come:

Creare una classe che contiene tutti i dati di sessione necessari memorizzati (chiamiamolo SessionData), più un ulteriore DateTime per quando l'ultima sessione è stata utilizzata. Quindi aggiungere alla classe di servizio (o qualsiasi altra classe) a staticConcurrentDictionary<string, SessionData>.

Quando un client effettua una chiamata al servizio, richiede che passi una stringa univoca che identifica la sessione (può essere generata casualmente sul lato client). Ogni volta che un client chiama il servizio, cerca la stringa di sessione nel dizionario e recupera i dati della sessione (e aggiorna il suo contenuto secondo necessità). Se non esiste, crea una nuova voce nel dizionario. Inoltre, ogni volta che si accede all'oggetto SessionData, aggiornare l''ultimo utilizzato' DateTime all'ora corrente. Un'attività in background dovrebbe cancellare periodicamente vecchie sessioni che non sono state utilizzate in un istante.

Ecco fatto: hai implementato le sessioni da solo. È ora possibile utilizzare InstanceContextMode.Single e non preoccuparsi che WCF crei correttamente le istanze della classe di servizio per sessione.

EDIT: Se si sta scrivendo il vostro servizio WCF con .NET 4.5 e applicazioni web si rivolge solo i browser moderni, è possibile utilizzare NetHttpBinding sul lato server e WebSocket sul lato client. NetHttpBinding supporta la sessione (quando si specifica SessionMode.Required).

+0

+1: non dicendo che il tuo suggerimento è imperfetto per iniziare, ma per implementare un meccanismo di sessione di produzione c'è un sacco di problemi da considerare o da prendere in considerazione: come il dirottamento di sessione (accidentale o di proposito), i timeout di sessione effettivi che ha senso per la tua applicazione, sessione (dati) persistenza/resilienza, nel caso in cui il server si riavvii (pianificato o non pianificato/crash), modifica simultanea della sessione (dati) da più richieste simultanee, ecc. –

+0

@ Christian.K: Molto vero. Non credo che le ultime due cose siano comunque fornite da WCF. La sicurezza è davvero un problema da prendere in considerazione, e per quanto riguarda la sicurezza dei thread ho pensato che ogni client avrebbe generato una chiave di sessione univoca e avrebbe eseguito al massimo una chiamata al servizio in qualsiasi momento, ma se questo non è il caso anche la correttezza deve essere curata. –

+0

@AllonGuralnek non sta utilizzando InstanceContextMode.Single avrà un impatto significativo sulle mie prestazioni? –

0

Questo link ti dà praticamente tutto ciò che devi sapere su questo (in generale, ovviamente).

Ma per preciso.MSDN dice di sessione WCF:

Sono esplicitamente iniziati e terminati dal chiamando applicazione

devo dire che non so di qualsiasi JS codice/quadro che consenta di memorizzare canale di comunicazione WCF esplicitamente aperto per mantenere viva la "sessione". (Non hai fornito il tuo codice cliente, quindi devo fare alcune ipotesi). La sessione WCF non è "basata su cookie". Non funziona "out of the box" dal tuo browser come sarebbe per l'applicazione web ASP.NET.

L'impostazione InstanceContextMode.PerSession rende il servizio WCF "pronto per la sessione" ma non è sufficiente per "forzare" una sessione.

+0

Cosa intendi per "cookie-based" per ASP.NET? se aggiungerò posso usarlo? posso avere una soluzione "pronta all'uso". –