2013-04-11 1 views
0

Мы создаем приложение, которое будет отправлять сообщения в браузер с помощью SignalR. У пользователя может быть несколько экземпляров браузера, и мы хотели бы, чтобы каждое сообщение отправлялось в соответствующий браузер. Наше понимание заключается в том, что ClientId ConnectionId позволит нам это сделать. Проблема, с которой мы сталкиваемся, - это доступ к ClientId ConnectionId или SessionId в соответствующие моменты времени в кодовой базе. Вот наш сценарий:Изолирование конкретного экземпляра браузера с помощью SignalR

Выполнение MVC Action и, как часть этой обработки, выполняется вызов конечной точки Biztalk. Выполнение Biztalk не выполнено (с точки зрения действия MVC) и не возвращается при завершении. Это по дизайну. Чтобы уведомить приложение MVC о том, что он был завершен, Biztalk отправляет сообщение в концентратор SignalR приложения MVC, вызывая конечную точку/myapp/signalr. Сообщение принимается SignalR, а затем должно быть перенаправлено в соответствующий экземпляр браузера.

Поскольку сообщение SignalR отправляется Biztalk, а не приложение MVC, ClientId соединения с SignalR не является тем, которое идентифицирует экземпляр браузера, который должен получать сообщение. Так что мы пытаемся реализовать, это похоже на шаблон обратного адреса, включая идентификатор экземпляра браузера ClientId экземпляра браузера, который инициирует вызов Biztalk в сообщении Biztalk. Когда Biztalk отправляет свое сообщение SignalR, одним из его содержимого является оригинал ClientId Значение ConnectionId. Когда SignalR обрабатывает сообщение из Biztalk, он может использовать подключаемый файл ClientId ConnectionId, включенный в сообщение, чтобы перенаправить это сообщение в соответствующий экземпляр браузера. (Да, мы знаем, что это не сработает, если браузер был закрыт и снова открыт, и мы в порядке с этим.)

Проблема, с которой мы сталкиваемся, заключается в том, что при первоначальной отправке сообщения Biztalk из нашего MVC Action мы не можем получить доступ к ClientId ConnectionId, поскольку он доступен только в Контексте концентратора. Это понятно, поскольку MVC Action не знает, какой контекст концентратора нужно искать.

Что мы пробовали в этом месте - передать SessionId через сообщение Biztalk и вернуть его в SignalR. Это решает проблему включения идентификатора экземпляра браузера в сообщение Biztalk и возвращения его в SignalR. То, что он вводит, заключается в том, что когда клиент подключается к концентратору, мы не можем получить доступ к сеансу (и, следовательно, к SessionId) в методе OnConnect концентратора.

Дэвид Фаулер опубликовал суть, которая, как сообщается, показывает, как сделать доступным только для чтения SessionState в концентраторе, но это не сработает. (https://gist.github.com/davidfowl/4692934) Как только мы добавим этот код в наши приложения, сообщения, отправленные SignalR, вызывают ошибку HTTP 500, вызванную SignalR, бросающей следующее исключение.

[ArgumentNullException: Value cannot be null.Parameter name: s] 
System.IO.StringReader..ctor(String s) +10688601 
Microsoft.AspNet.SignalR.Json.JsonNetSerializer.Parse(String json, Type targetType) +77 
Microsoft.AspNet.SignalR.Json.JsonSerializerExtensions.Parse(IJsonSerializer serializer, String json) +184 
Microsoft.AspNet.SignalR.Hubs.HubRequestParser.Parse(String data) +101 
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest request, String connectionId, String data) +143 
Microsoft.AspNet.SignalR.<>c__DisplayClassc.<ProcessRequest>b__7() +96 
Microsoft.AspNet.SignalR.<>c__DisplayClass3c.<FromMethod>b__3b() +41 
Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +67 

Независимо от режима, который мы устанавливаем SessionStateBehavior (как показано сутью Дэвида Фаулера) мы либо получить это исключение при отправке сообщения в Хаб или SessionState равно нулю, когда мы находимся в OnConnect концентратора.

Итак, что же мы спрашиваем, как люди обновляют соответствующий клиент при работе с этим типом отключенных сообщений в SignalR?

+0

Когда вы говорите ClientId, вы имеете в виду идентификатор соединения? –

+0

Да. Обновлено до правильного слова – dbelcham

+0

Таким образом, похоже, что это не техническое решение. Я считаю, что правильное решение состоит в том, чтобы иметь лучшую архитектуру, которая не полагается на возврат сообщений пользователю. Сейчас мы меняем направление. – dbelcham

ответ

0

Если вы хотите отправить данные клиентам за пределы обычного запроса на концентратор, я бы рекомендовал иметь статический параллельный словарь на вашем концентраторе, который управляет вашими пользователями и сопоставляет их с соответствующими идентификаторами соединения.

При таком подходе вы можете отправить любому пользователю в любой точке на основе их сопоставленного идентификатора соединения. Поэтому при отправке данных в Biztalk все, что вам нужно сделать, это отправить идентификатор пользователя (созданный вами), а затем, когда данные возвращаются в SignalR, вы можете найти ConnectionId (если таковой существует) для данного идентификатора пользователя.

Наконец, вы можете управлять своими сопоставлениями пользователей, добавляя пользователей в ваш параллельный словарь в OnConnected, добавляя только в том случае, если они не присутствуют в OnReconnected и удаляются в OnDisconnected.

+0

Проблема заключается в том, что, когда у пользователя есть несколько экземпляров открываемого приложения/страницы, просто отправка идентификатора пользователя в BizTalk недостаточно, чтобы полностью идентифицировать экземпляр браузера, на который должно быть отправлено возвращаемое сообщение. Например, у Джо есть два экземпляра браузера, открытый с ClientIds 123456ABC и DEF987654. Если все, что мы отправляем в BizTalk (и оно возвращается нам), это «Joe», тогда мы не знаем, к какому экземпляру браузера нужно отправить сообщение. – dbelcham

+0

Нам нужно, чтобы иметь возможность использовать уникальный идентификатор браузера (который, на мой взгляд, ClientId), и отправить его в Biztalk, чтобы он мог быть возвращен в сообщении Biztalk. Когда сообщение отправляется в Biztalk за пределами концентратора и контекста, у нас нет доступа к ClientId ... так что альтернатива становится вопросом. – dbelcham

+0

Вы все равно можете это сделать, сопоставляя пользователей с идентификаторами соединения в своем концентраторе. Например, вместо того, чтобы быть сопоставлением идентификатора пользователя -> соединения, это может быть сопоставление пользователя -> браузер [], где браузер имеет уникальный идентификатор, который сопоставляется идентификатору соединения. На этом этапе вам просто нужно отправить идентификатор browserID в biztalk, а затем вы можете посмотреть его, когда он вернется к конечной точке SignalR. Все время идентификаторы браузера все еще управляются OnConnected, OnReconnected, OnDisconnected и т. Д. –

 Смежные вопросы

  • Нет связанных вопросов^_^