Scope in web project

I have been reading the docs etc and am a little confused with regard to the “scope” of objects. I understand it from a desktop perspective but when dealing with a web project are all “Public” scopes public to the session or to the app. If so then is is just the App object that can have objects that can have a truly Public scope across the whole app?

“Public” simply means that the method or property can be called by code outside of the class in which it is defined. The way you phrased the question makes me think that you might be confusing this with single vs. multiple instances and data storage.

You have a single instance of the App class (a unique situation since most classes can have many instances). So a value in App.MyProperty is ‘global’ in the sense that there is only one App.MyProperty. If App.MyProperty is Public then code which is part of any other class/module can access it. If it’s Protected or Private only code which is part of App can access it.

You have an instance of Session for every connection to your web app. So Session.ClientName might hold Alice for one connected user, and Bob for another. Any code called in response to a Session, WebPage, or WebControl event which accesses Session.ClientName will get the value unique to the Session representing the connection which raised the event. Alice will get her name, Bob will get his.

If Session.ClientName is Public, then code which is not part of Session can get it. You could have a Thread get the array of all Sessions, find Bob’s instance, and call ClientName to get “Bob”. If Session.ClientName is Protected/Private, then the code that’s part of your Thread will not be able to call it. Only code that’s part of Session can call it.

Modules are a little bit different in that a method/property can be Global (instead of Public). This means it can be called any where without the module’s name, i.e. MyGlobalMethod. If Protected, then it can be called any where using the module’s name, i.e. MyModule.MyProtectedMethod. Private means only code in the same module can call it. This is related to the fact that a module is not a class and there are no instances of it. It’s just a convenient place to store methods and properties which stand on their own and do not fit in a class.

Wow, what a brilliant explanation, that has really helped a lot.

Can I just get a bit more clarification regarding “Session.ClientName is Public”. Am I correct that the main app could access the session.clientname to be able to do some magic but the individual session.client name would be alice for her session and bob for his session?

Yes. If Session.ClientName is Public, then any code can access it. What is returned will depend on which instance the code is calling .ClientName on. Both Alice and Bob are connected (in that order). Consider the code below:

  Dim objSession As WebSession
  Dim s As String
  Dim i, c As Integer
  
  c = App.SessionCount - 1
  
  For i = 0 To c Step 1
    objSession = App.SessionAtIndex(i)
    s = objSession.ClientName
  Next

On the first loop objSession has Alice’s Session instance, and .ClientName will return her name. On the second loop you’ll get Bob’s.

(Note: this code obviously doesn’t compile unless you add a ClientName property and fill it with something in Session.Open.)

If Session.ClientName is Public, then you can run this code any where. In an App event, in a Thread event, in a method of any class or module. If Session.ClientName is Protected/Private, then the code above would only work in an event or method of Session itself.

I should probably throw this in there: a shared class method or property is “global”. You do not need an instance to call a shared method/property, and shared properties hold one value that is the same for all instances of the class. Again, Public means accessible by any other code, Protected by code in the class or its subclasses, Private by code only in that specific class.

Thank you so much for the info, the penny hasnt yet totally dropped but it is getting close :wink: I can see the public session thing being really useful for sending messages to sessions and being able to see what people are doing within the app.

Keep in mind that outside of events you will have to setup a WebSessionContext to call certain methods off a Session / WebPage / WebControl.

In the sample code above if you wanted to do something like

App.SessionAtIndex(i).WebPage1.myAlertLabel.Text = "You have mail!"

you would have to setup a WebSessionContext before calling myAlertLabel.Text.

Otherwise, yes, you can loop through the sessions and do fun stuff.

Almost forgot…you’re welcome. Glad to be of assistance.

Xojo is an amazing development language, just wish I had taken it more seriously when I looked at RB back in 2010 but to be honest I think it has come a long way in the last 4 years.

I am thinking about having an Admin option to shut the server down for updates etc and the option would notify all the users every 10 minutes from 30 minutes out to tell them the server is going down. At 5 minutes it would remind them every 1 minute and at 0 it would kill the user sessions and shutdown the app. Havent really thought about how to write it yet but I am think a thread should do the trick.

Given the nature of the task (execute every X mins) I would use a Timer.

Note that there are Timers and WebTimers. Timers run server side regardless of whether or not there are any sessions and are not associated with a particular session or page. WebTimers are dropped on a page and run for each session which has that page open.

I would create a Timer subclass and store an instance in a global location (i.e. App property, module property, shared property of a class). In your Timer subclass Action event, loop through the sessions and alert the users however you like (don’t forget WebSessionContext). You can change the Timer period mid way through (i.e. 10m to 1m) and when the time is up shutdown the app.

Ok, I am going to have a play with that next week and maybe get it to email me when their is 10 minutes to go before shutdown and then 1 minute before shutdown. Might even add a link to the email and use a special url handler to abort the shutdown which would message all the users to say the shutdown had been postponed. I am sure someone could write this as a plugin object you could add to a web project. Not sure I am up to that yet :wink: