Calling a method as another WebSession?

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.

Thanks.
Is that not what the code in my first post, taken from an example in the Language Reference and which doesn’t work, should already do?

Try setting sessionContext to nil just before the Next statement. It could be that they’re not getting destroyed and conflicting with one another.

Still not working.

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.

Do you see the same as me?

Thanks.

I’m not near a computer today.

That said, try testing this with different browsers instead of different tabs on the same browser.

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.

uh… that’s not going to work reliably.

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 get the same behaviour.
Does the code quoted above work on your side?

This is very similar to the code from the example and, in my case, doesn’t work either (all methods running on the calling session).

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.

I’ve found these feedback cases:

feedback://showreport?report_id=60734
It was accepted as a bug and suddenly closed as “By Design”.

feedback://showreport?report_id=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.

I use Timer.Calllater to decouple the action from the session. You can have a look at Xojo Project to see how.

3 Likes

Oh yes, this way works!
Thank you!

1 Like

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.

1 Like

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).

Thank you.