2012-12-06 4 views
8

У меня есть службы WCF, потребляемый AJAX клиента с использованием SOAP 1.2Почему InstanceContextMode.PerSession ведет себя как PerCall при использовании wsHttpBinding?

Web.config:

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

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

Из того, что у меня есть read, я должен использовать <security mode="None"/>, так как сервис подвергается с «WsHttpBinding» связывания реализует WS-Security WS- * семейства спецификаций веб-сервисов. Поскольку привязка использует безопасность, запрос будет отклонен, поскольку AJAX не поддерживает контекст безопасности.

Мое поведение службы WCF определяется с InstanceContextMode.PerSession:

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

но когда я потребляю его, служба ведут себя, как PerCall и каждый вызов запускает новый экземпляр WCF вместо использования текущего экземпляра.

Почему InstanceContextMode.PerSession ведет себя как PerCall при использовании wsHttpBinding?

Что я могу сделать?

+0

Возможный дубликат: http://stackoverflow.com/questions/4767102/wcf-sessions-with-a-wshttpbinding-and-without-windows-security – ErnieL

+0

@ErnieL Спасибо, но используя для меня это не вариант, поскольку он не будет работать с моим клиентом AJAX. –

+0

Сам по себе wsHttpBinding не поддерживает сеансы. – ErnieL

ответ

3

Сессии при использовании по HTTP поддерживаются только WCF при использовании сеансов безопасности или надежных сеансов. Если вы не можете использовать ни то, ни другое, вы должны сами реализовать механизм сеанса. Если вы контролируете как клиент, так и серверную сторону, это будет довольно легко сделать. Вот как это делается:

Создайте класс, в котором хранятся все данные сеанса, которые вам нужно сохранить (назовем его SessionData), плюс дополнительный DateTime для последнего сеанса. Затем добавьте в свой класс обслуживания (или любой другой класс) staticConcurrentDictionary<string, SessionData>.

Когда клиент совершает звонок к вашему сервису, попросите его передать уникальную строку, которая идентифицирует сеанс (его можно произвольно создать на стороне клиента). Всякий раз, когда клиент вызывает вашу службу, просмотрите строку сеанса в словаре и извлеките данные сеанса (и при необходимости обновите его содержимое). Если он не существует, создайте новую запись в словаре. Кроме того, каждый раз, когда вы обращаетесь к объекту SessionData, обновите «последний использованный» DateTime до текущего времени. Фоновая задача должна периодически очищать старые сеансы, которые не использовались в то время.

Вот и все - вы внедрили сеансы самостоятельно. Теперь вы можете использовать InstanceContextMode.Single и не беспокоиться о том, что WCF правильно создает экземпляры вашего класса обслуживания за сеанс.

EDIT: Если вы пишете службы WCF с .NET 4.5 и вы веб-приложение предназначено только современные браузеры, вы можете использовать NetHttpBinding на стороне сервера и WebSocket на стороне клиента. NetHttpBinding поддерживает сеанс (при указании SessionMode.Required).

+0

+1: Не сказал, что ваше предложение испорчено для начала, но для реализации готового сеансного механизма есть целый пакет проблем, которые следует учитывать или заботиться: например, захват сеанса (случайно или по назначению), фактические таймауты сеанса, которые имеет смысл для вашего приложения, стойкость/устойчивость к сеансу (данным), в случае перезапуска сервера (запланированного или незапланированного/аварийного), одновременной модификации сеанса (данных) несколькими одновременными запросами и т. д. –

+0

@ Christian.K: Very правда. Я не верю, что последние две вещи предоставлены WCF. Безопасность - это действительно проблема, которую нужно учитывать, и что касается безопасности потоков, я предположил, что каждый клиент будет генерировать уникальный ключ сеанса и будет выполнять не более одного вызова службы в любой момент времени, но если это не тот случай, когда безопасность потоков и правильность также необходимо позаботиться. –

+0

@AllonGuralnek не использует InstanceContextMode.Single будет иметь большое влияние на мою производительность? –

0

Это link дает вам почти все, что вам нужно знать об этом (вообще, конечно).

Но точно.MSDN говорит о WCF сессии:

Они явно инициированного и завершенного вызывающего применения

Я должен сказать, что я не знаю о каких-либо JS код/​​рамки, которые позволят Вам хранить явно открыл канал связи WCF, чтобы сохранить вашу «сессию» вживую. (Вы не указали свой код клиента, поэтому я должен сделать некоторые предположения). Сессия WCF не является «основанной на файлах cookie». Он не работает «из коробки» из вашего браузера, как это было бы для веб-приложения ASP.NET.

Установка InstanceContextMode.PerSession делает вашу службу WCF «готовой к сеансу», но этого недостаточно для «принудительного» сеанса.

+0

Что вы подразумеваете под «cookie-based» для ASP.NET? если я добавлю , могу ли я его использовать? я могу получить «из коробки». –