0

I've created an asp.net page for work that allows customers to look up users in AD, and then request to have them added as delegates to Rightfax numbers, which can also be searched for. Rightnow I'm storing public variables used by the back end and front end of the project in a CurrentSession class inherited by the pages thats supposed to be unique to each user, but I'm still seeing occasional issues where variables will 'bleed' from one session to another. Sometimes I'll go to the page and the list of AD users is already populated with users from another session\user.

I'm wondering what the best method is for storing variables in this scenario. Should I be using cookies rather than a current session class? Are there any good guides/tutorials that go over variable management for asp.net pages? I'm typically a desktop developer so I'm not particularly familiar with this kind of issue.

user2312463
  • 1
  • 1
  • 1
  • 1
  • In IIS Admin, find the application pool that the site is using, and in its "Advanced Settings..." make sure that "Maximum Worker Processes" is set to 1. – Andrew Morton Aug 31 '21 at 15:32
  • @AndrewMorton Why? What's the purpose of that? – mason Aug 31 '21 at 16:20
  • Please post a [mcve] showing your code that suffers from this. Instead of asking "what's the best way to code it" you should formulate your question as "Here's what I've tried and it's not working properly because of X, how do I fix it?" – mason Aug 31 '21 at 16:20
  • @mason The names have changed but this problem remains the same: [ASP.NET session state and multiple worker processes](https://stackoverflow.com/q/2147578/1115360). We might as well check for simple things first. – Andrew Morton Aug 31 '21 at 17:04
  • @AndrewMorton That's good to know. Your original comment lacked that context, which is why I asked. Looks like you only need to do this for web garden mode. I've not heard that term in years, I wonder if it's still around. – mason Aug 31 '21 at 17:07
  • @mason TBH, I was expecting the OP to report back that it was already set to 1 and any further effort along that line would have been wasted unless they said otherwise. – Andrew Morton Aug 31 '21 at 17:11
  • @AndrewMorton Fair enough. My guess is there's some static variables being used, or whatever the VB equivalent is of a C# static variable. But without further info we can't really answer this question, so I've voted to close. – mason Aug 31 '21 at 17:19
  • @AndrewMorton Thanks for the suggestion, I just checked my app pool settings in IIS and the maximum worker process was set to 8 (one process for each CPU core on the server). I had set it to that months ago when trying to speed up API response time, but I've since solved that by pre-chaching certain values. I'll also review my code to make sure I'm not using a public global variable instead of the session class version of the variable. I know that had caused me some grief earlier on in the project, but as far as I know I've gotten everything converted to session variables now – user2312463 Aug 31 '21 at 17:42
  • @user2312463 Two useful things to do when using session state: use an Enum for the names, so you can write, e.g. `Dim username = CStr(Session(SessionKey.Username))` (where `SessionKey` is simply a suggestion for the name name of the Enum) and not have to go and find the name you used, and use out-of-process session state so that if the worker gets recycled then any current users don't lose their sessions. – Andrew Morton Aug 31 '21 at 17:50
  • @user2312463 Unless you're using Application variables (like Session, but scoped to the app), public global variables are individual to each session. – Andrew Morton Aug 31 '21 at 18:14
  • Does this answer your question? [Losing Session State](https://stackoverflow.com/questions/3515947/losing-session-state). In particular, [this answer](https://stackoverflow.com/a/44024416/1115360). – Andrew Morton Sep 02 '21 at 12:54

1 Answers1

-1

the whole jump to the web, and that of session managment, or varible managment is a huge topic. And it is often a challenge, since the concpets are very different then desktop.

So, I mean, when a user clicks a button, the web page is posted up to the server. The page is found, loaded, variables start from scratch. Code behind runs, page is sent back down to client AND THE PAGE SERVER SIDE IS TOSSED out!

So, the above is a new challenge, due to that so called "state-less" nature of web pages.

As for session bleeing to other users? Hum, that should not occur. However, session() can be VERY fragle. Due to time outs, due to some execution error in code, the app pool can and will often re-start.

So, I strong recommend that you run the script and turn on SQL servre based sesison management. Once done, then session() becomes bullet proof - and always works.

As for values bleeding to other users? No way - I not seen that.

(of course, you did not mention or note what authentication provider you are using (or even if users have to logon).

However, while I OFTEN use session, and even to pass values from one page to the next? (absolute hate parameters in the URL - messy and often security risk if things like PK id etc. are included)).

However, some big sites say like amazon use parameters and values in the URL a lot. They do this since then the server side does not get over-loaded and have to keep track or hold those values. However, unless you building the next facebook, or huge + high volume web site, then session() is quite much the standard approch to keep values active for your code.

However, lets assume we toss up a grid, and the user selects that product?

We set in session() say that PK id, and hten jump to the next page say to buy that house?

Well, now if you open a new tab - even a different browser, launch that grid, select a house and jump to the page to display that information? You can't use session since as noted it will overwrite the values in the other page.

So, you can try and build a bunch of fancy classes and all kinds of handstands, but I just simply transfer the session() values to ViewState.

ViewState is per page, and session() is global to that one user.

So, if I need 10 variables and value for a given part of the application, say like this:

<Serializable>
Public Class clsProjectInfo

    Public ContactID As Integer = 0
    Public ContactGeneralID As Integer = 0
    Public PortalComp As String = ""
    Public ProjectHeaderID As Integer = 0
    Public QuoteNum As Integer = 0
    Public UploadGroup As Integer = 0
    Public txtNotes As String = ""
    Public ProofID As Integer = 0

End Class

So say in the page that we select the project - setup a whole buch of values?

Then the above var will be in session(), but ONLY for pasing to the next page.

So the project view page that needs all of the aobve values to work?

The page load code will look like this:

Dim cPinfo As New clsProjectInfo

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If IsPostBack = False Then

        cPinfo = Session("Pinfo")
        ViewState("Pinfo") = cPinfo

    Else

        cPinfo = ViewState("Pinfo")

    End If

So we only EVER use session to pass that "bunch of values" to the next page, but always first thing we do is transfer from session() to viewstate. That way if the user opens another tab, or selects a different house in that 2nd browser, jumps to the view details, we only ever used session() to pass the values to the next page, but from that point on, always used ViewState.

Now the above simple idea might not work for all cases but it does for most.

So, don't adopt huge number of session() values, and as always even in desktop, global vars and values should not be required.

So session() for a given user will most certainly often "stomp" on top of other parts of the application. If session() is spilling over between different users? That should not occur, never occur and means as noted something else is going wrong here.

So even for desktop software? Each form, or page or part of the application tend to have and need a set of values. So, I build plane jane simple class as per above. And then you can with great ease pass ONE class thing with the 5-10 variables in it. that way I don't wind up with 50 variables in session() - which is a nightmare from coding point of view (let alone to remember the varaiables). But with above passing the one class, then you just passing ONE thing and you get intel-sense too boot.

And no doubt that group of variables often has to be passed to routine. So beofre above, I often like had to pass like 5-6 values to some function or sub - and what a pan.

So old way:

    Call SaveAfterUpload(AjaxFileUpload1, session("QuoteNum", session("ContactID",
                 session("UploadGroup"), strCleanFile, session("txtNotes"), session("PortalComp")

but now we can go:

    Call SaveAfterUpload(AjaxFileUpload1, cPinfo.QuoteNum, cPinfo.ContactID,
                         cPinfo.UploadGroup, strCleanFile, cPinfo.txtNotes, cPinfo.PortalComp)

But, then again, since we have that class, then above now becomes

    Call SaveAfterUpload(AjaxFileUpload1, cPinfo)

So, don't put a truck load of values into session().

Create "groupings" of the values.

And what is even SUPER great?

often some of the client side JavaScript code needs those values.

So, you THEN wind up dropping in a boatload of hidden fields or hidden cnotrols for those values.

But, with the above class? I can pass + have the whole mess client side like this:

        cPinfo = ViewState("Pinfo")   ' this no doubt occured on page load

        ' copy Pinfo to browser side 
        MyUpLoadInfo.Value = JsonConvert.SerializeObject(cPinfo)

MyUpLoadInfo is just a simple asp.net hidden field like this:

            <asp:HiddenField ID="MyUpLoadInfo" runat="server" ClientIDMode="Static" />

But, now in place of those 5-6 hidden fields, I have the above cPinfo now for use in the client side.

eg this:

               MyUpLoadInfo = document.getElementById("MyUpLoadInfo")
               Pinfo = JSON.parse(MyUpLoadInfo.value)

               // now I have all values such as
               Pinfo.txtNotes
               Pinfo.QuoteNum

So, by building that class or set of variables, I can now pass down the WHOLE mess in one shot to the client side, and now my JavaScript code can with great ease use all those variables client side!!

And it turns out that for each section of a typical application?

 about 5-10 variables are only required

 often they are required client side - and with above we can

 Most if not ALL of the routines in that application part need those vars
 (including subs and functions, so now we can pass 5-10 values, and we don't
  have huge long list of messy parameters in all of those subs and functions).

We can modify the class - add more variables, and the dozen routines now all have that extra variable - yet we don't change the code, or even change the sub/function calls to have that extra new variable in that code. (and this applies to client side js code if we need/require that group of values for the browser code.).

So we thus don't have huge numbers of global vars.

we don't wind up with a gazillion number of separate session values.

we vast improve the ability to pass those values to subs/functions.

And we even can pass that set of values to the client side with great ease.

So any global var can be in session, but those global vars are NEVER to be used for passing value from page to page and code calls for a given part of your application.

And if you want to support more then one page or browser by the user? Then adopt the standard that on first page load you transfer that session class to viewstate.

Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51
  • Thank you very much for your reply! Thats a lot of useful information to go over, I'll see what I can get implemented in my project. – user2312463 Aug 31 '21 at 17:44