2012-12-06 16 views
8

Mam usługa WCF spożywane przez klienta AJAX używając mydła 1,2Dlaczego InstanceContextMode.PerSession zachowuje się jak PerCall podczas korzystania z wsHttpBinding?

Web.config:

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

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

Od czego mam read, muszę używać <security mode="None"/> ponieważ usługa narażony na „wsHttpBinding” wiązania implementuje specyfikację usług WWW WS-Security z rodziny WS- *. Ponieważ powiązanie korzysta z zabezpieczeń, żądanie zostanie odrzucone, ponieważ AJAX nie obsługuje kontekstu zabezpieczeń.

Moje zachowanie jest zdefiniowana usługa WCF z InstanceContextMode.PerSession:

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

ale kiedy go spożywać, zachowują się jak PerCall serwis i każde wezwanie rozpoczyna nową instancję WCF zamiast przy użyciu bieżącej instancji.

Dlaczego InstanceContextMode.PerSession zachowuje się jak PerCall podczas używania wsHttpBinding?

Co mogę zrobić?

+0

możliwy duplikat: http://stackoverflow.com/questions/4767102/wcf-sessions-with-a-wshttpbinding-and-without-windows-security – ErnieL

+0

@Eniel Dzięki, ale używając nie jest dla mnie opcją, ponieważ nie będzie działać z moim klientem AJAX. –

+0

Samo wsHttpBinding nie obsługuje sesji. – ErnieL

Odpowiedz

3

Sesje, gdy są używane przez HTTP, są obsługiwane tylko przez WCF podczas korzystania z sesji zabezpieczeń lub niezawodnych sesji. Jeśli nie możesz tego użyć, musisz samodzielnie wdrożyć mechanizm sesji. Jeśli kontrolujesz zarówno klienta, jak i serwer, łatwo będzie to zrobić. Oto, jak:

Utwórz klasę zawierającą wszystkie przechowywane dane sesji (nazwijmy ją SessionData) oraz dodatkową DateTime dla ostatniej sesji. Następnie dodaj do swojej klasy usług (lub dowolnej innej klasy) a staticConcurrentDictionary<string, SessionData>.

Gdy klient wykonuje połączenie z Twoją usługą, wymaga przekazania unikalnego ciągu identyfikującego sesję (może być losowo wygenerowany po stronie klienta). Za każdym razem, gdy klient wywołuje twoją usługę, wyszukaj ciąg sesji w słowniku i pobierz dane sesji (i zaktualizuj zawartość w razie potrzeby). Jeśli nie istnieje, utwórz nowy wpis w słowniku. Ponadto, za każdym razem, gdy uzyskujesz dostęp do obiektu SessionData, zaktualizuj "ostatnio używany" DateTime do bieżącego czasu. Zadanie w tle powinno okresowo usuwać stare sesje, które nie były używane od jakiegoś czasu.

To wszystko - sam wdrożyłeś sesje. Możesz teraz używać InstanceContextMode.Single i nie martw się o to, że WCF poprawnie tworzy instancje klasy usług na sesję.

EDIT: Jeśli piszesz swoją usługę WCF z .NET 4.5 i aplikacja internetowa jest kierowana tylko nowoczesnych przeglądarek, można użyć NetHttpBinding po stronie serwera i websocket po stronie klienta. NetHttpBinding obsługuje sesję (podczas określania SessionMode.Required).

+0

+1: Nie powiem, że twoja sugestia była wadliwa na początku, ale aby wdrożyć mechanizm produkcji gotowy do produkcji, istnieje cała masa problemów, które należy rozważyć lub zająć się: jak przejmowanie sesji (przypadkowo lub celowo), rzeczywiste czasy sesji, które sensowne dla twojej aplikacji, trwałości/odporności sesji (danych), na wypadek ponownego uruchomienia serwera (planowane lub nieplanowane/awarie), jednoczesnej modyfikacji sesji (danych) przez wiele, jednoczesnych żądań itp. –

+0

@ Christian.K: Very prawdziwe. Nie sądzę jednak, aby ostatnie dwie rzeczy były dostarczane przez WCF. Bezpieczeństwo jest rzeczywiście kwestią, którą należy wziąć pod uwagę, a co do bezpieczeństwa wątków zakładałem, że każdy klient wygeneruje unikalny klucz sesji i wykona co najwyżej jedno połączenie z usługą w danym momencie, ale jeśli tak nie jest, to bezpieczeństwo wątków i należy również zająć się poprawnością. –

+0

@AllonGuralnek nie używa InstanceContextMode.Single będzie mieć znaczący wpływ na moją wydajność? –

0

Ten link daje Ci prawie wszystko, co musisz wiedzieć na ten temat (ogólnie rzecz biorąc).

Ale do dokładności.MSDN mówi o WCF sesji:

Są one wyraźnie zainicjowany i zakończony przez wywołującego aplikacji

muszę powiedzieć, że nie wiem, o dowolnej kodu JS/ramy, które pozwalają na przechowywanie jawnie otwarty kanał komunikacji WCF, aby utrzymać swoją "sesję" przy życiu. (Nie podałeś kodu klienta, więc muszę przyjąć pewne założenia). Sesja WCF nie jest "oparta na plikach cookie". Nie działa "po wyjęciu z pudełka" z przeglądarki, tak jak w przypadku aplikacji internetowych ASP.NET.

Ustawienie InstanceContextMode.PerSession powoduje, że Twoja usługa WCF jest "gotowa do sesji", ale nie wystarczy "zmusić" sesji.

+0

Co masz na myśli mówiąc o "cookie" dla ASP.NET? jeśli dodam , więc czy mogę go użyć? czy mogę mieć rozwiązanie "od razu po wyjęciu z pudełka". –

Powiązane problemy