WebPage: Instantiate or not? Best practice?

I would like to understand the implications of (a) simply adding webpages (implicit instances) to a webproject 2.0 and using them for all users vs. (b) instantiating webpages (non implicit) per session and referencing them in a session property.

  1. When a user surfs to one webpage and has it displayed in his browser, can data he enters get mixed up with other users, working on the same page? Or are both ways safe, a and b?

  2. Which one is faster to display to the user and which one is using less memory, a or b?

I hope anyone has time to shed a light on this and share some knowledge.

Thanks!

Data will not get mixed up, but there are security and memory reasons speaking against implicit instances of WebPages: Implicit Instances and WebPages

Would this discussion still be valid for web 2.0?

1 Like

Very good question. I’ve been asking myself this questions as well. Especially as it is not trivial to test it by your own, if you are not sure how it is working :wink:

Well… let’s talk about this.

The web framework (both 1.0 and 2.0) are designed to keep user data separate. That is, that only one user’s data is being accessed at any given time by default, and while WebPage instances are unique per session, there are patterns in a web app that can cause cross contamination:

Static Variables

Static variable are, by definition, persistent across all instances of a class and using them can cause data to cross over into other sessions. For example, if you were to:
  1. Create a new web project
  2. Drag a label onto WebPage1
  3. In WebPage1.Open(ing) put the following code:
Static n as integer
n = n + 1
Label1.value = n.ToString
  1. Run and connect to the app a few times.

Each time a new user comes to your app, n is incremented. If you did this to save a user’s password in a Static, it would be available across all sessions.

In other words… do not make a WebPage instance Static.

Global Properties

Another way you can get yourself into trouble is by using properties on Modules or Shared Properties on Classes. Just like in a single-user project, these things are global across all sessions, so it's important to keep track of what you are doing. The easiest way to keep properties separate is to add them directly to the Session object.

If you wanted to organize session-specific properties together, I suggest doing so using a class that is added to a Session as a property itself. For instance, you could make a class called Settings which has Name, Company and Phone properties and add an instance (lets say userSettings) of that class to the Session on Open(ing). When you need that information, you would refer to it like this:
Var name As String = Session.userSettings.name

So in terms of WebPages, if you’re going to keep track of them yourself, make sure you put them on the Session itself. Keep in mind that the Session does already keep track of them for you, so you don’t have to unless you will need to refer to it again later. This brings me to something I would be remiss not to discuss at this point…

Memory Leaks

You can't have a discussion about instantiating WebPages at runtime without touching on this. Memory Leaks are, by definition, memory that gets "leaked" because objects cannot be destroyed when the program is done with them.

The easiest way to create a memory leak in a web project is to add a property to a WebPage or WebControl (or one of its subclasses) which refers to an object which can contain that object. For instance, if you were to add a WebContainer to your project and for simplicity’s sake, you add a property which refers to the WebSession to which the container belongs. The problem comes in when the user has gone away and the app is trying to clean things up. Even though the Session instance gets released from the app itself, because there is a reference to the Session from the container, it cannot be destroyed. Here’s an example of what I’m talking about:

Inherently, WebSessions keep references to the WebPages contained within. The same goes for controls on a WebPage. If you were to do what I described above, and create a reference from a WebContainer back to the Session itself (the blue line), you’ve created what’s called a circular reference. When the Session is no longer needed, the web framework releases its reference to the Session instance. Normally this would cause the underlying framework to destroy the session and then the pages and then the container as each of the references to those things went away. If however you had created the extra reference from the container to the session, it will never be destroyed because there’s always a reference.

In real world terms, imagine a game where people hold hands (okay, not now in the midst of the 2020 pandemic, but bear with me for a moment). In this game, you can only release one hand if the other hand is not holding onto something else.

  1. Three people are playing. Mike, Carol and Alex.
  2. Carol holds onto one of Mike’s free hands.
  3. Alex holds onto Carol’s free hand.

Now at any given time, this chain can be broken up if Alex or Mike lets go of Carol’s hand. But what happens if Alex takes Mike’s free hand. According to the rules, no one can let go of anyone else until the end of the game.

5 Likes

@Greg_O_Lone if I am putting all properties and methods into the different webpages, would that me safe enough? Plus skipping modules and for classes avoiding shared properties.

Reason why I’m asking is that I’m working on some larger projects which need some kind of structuring of my code.

Yes, that would work. Remember, when a web page is shown there’s a physically different instance for each running session. Same for any controls and properties on those pages.

If you need something that will live in a Module somewhere, I suggest using a dictionary whose key is a Session Identifier where the value gets you the values that are unique to that particular session.

2 Likes

@Greg_O_Lone many thanks for your time. These are important information. Since Web 1.0 I had a “bad” feeling about a few things I did. These clarifications are very helpful!

1 Like