In a WebApp, I added an Update method to the Session object. When there are several sessions open and something is modified in one, the others should update.
After having tried manually, with no luck, I checked the examples and eventually found what I thought would work:
For i As Integer = 0 To App.SessionCount - 1
Var sessionContext As New WebSessionContext(App.SessionAt(i))
MessageBox("The app will be shutting down in 5 minutes.")
Next
Even the documentation states my expectation: this should show a MessageBox in every session. In fact, all message boxes actually show in the calling session, so the example doesn’t work.
How can I invoke the function (MessageBox or my Update method) in the other sessions?
Create a WebSessionContext instance in code by passing in the Session.Identifier of the session you want to target. As long as the instance is around, commands will be sent to that session. When you’re done with it, let it go out of scope or set it to Nil.
Steps to reproduce:
I tried in a blank project. Put a WebButton in the default window with this code:
For i as Integer=0 To App.SessionCount-1
Var sessionContext As New WebSessionContext(App.SessionAt(i))
MessageBox "Test"
sessionContext=nil
Next
And run. In the browser (Safari, in my tests), make a new tab and create a second session (copying and pasting the URL of the first tab). Choose whichever tab you want and click the button. You’ll get the two message boxes in the same tab.
The way I do this in TP_WebKit for the MessageAllSessions function is that the Session class has a method that does the handling. The for loop looks similar to this:
for i as Integer = 0 to App.SessionCount - 1
// written in post editor, may need an extra cast
var oTarget as Session = App.SessionAt(i)
oTarget.ReceivingMethod
next i
In my opinion this code encapsulation is a little cleaner. You can see it working in action with the demo here.
Basically, you can do that but you must not make any calls into the Xojo Web Framework. Once your code needs to do that, the system we use for figuring out which session is in the foreground no longer has the hints it needs to get things right.
I know we’ve posted this before, but I can’t find it on my phone so…
When an event comes in from a browser, a WebThread is created which has an indication of which session it is attached to. Internally we use the information from the current thread to determine which session any code that is running should be sent to.
The mechanism I described, using WebSessionContext, adds a “hint” to the top of the stack so that when the framework goes looking for “where should I execute this command?” it finds the current WebSessionContext and uses that instead of the thread model.
Anything else will appear to work great on your local machine with a single user and fail spectacularly and risk cross-session data contamination when deployed with multiple users at runtime.
I’ve gone to check how I implemented it. I do include some extra magic to clear the session context and re-establish one. It appears I ran into an issue establishing context as well and found myself a workaround.
I’m sorry to report that my forum code probably won’t work. I was trying to be helpful from memory. I’ll refrain from doing so in the future.
In my library I use a workaround to clear the context before establishing one since I clearly ran into this session context issue myself. You could ask Xojo for an official example.
<https://xojo.com/issue/61449>
With this note:
“WebSessionContext is explicitly for places where you do not have a session… things like Timers, Socket Events, etc.”
Indeed, my code is in a place where the session is well known. So a WebSessionContext is not a solution in this case (I don’t know why it’s restricted to a working session).
And now I understand @Tim_Parnell saying the context should be cleared before attempting this method.
After reviewing the code, Wayne is correct. WebSessionContexts can only be created from within a main thread event. Timer events, Socket events, App events, etc. If you look at the docs page, we had intended that it would throw an exception if you tried to create one from within a session.
The documentation says it should work on “session-less” events; I couldn’t find a list of these (I knew sockets were like that, but not the others (or not sure)).
I understand it’s not easy to document a list of events (or classes?) that have no session, so I guess I’m not the only one getting this issue.
And that is why I followed this track. I first read the documentation and though “I’m not sure which events are without sessions”, and, also, “there has to be ways to execute methods in other sessions” so I tried anyway (using the code you gave).
Then I didn’t get any exception nor error; just the method running on the same session. It’d be nice to get an exception in this case (or even better, make calling a method to another session workable).