How can I count a specific session variable? - c#

I want to know if i can count a specific session variable.
I want to make a count of how many users are currenty logged in to the site and how many users are visiting the site right now.
Here is what i did (code)
public void Session_OnStart()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}
public void Session_OnEnd()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] - 1;
Application.UnLock();
}
This code works fine, But now I got no idea how to count users that are logged in. I want to do something like that:
public void Session_OnStart()
{
if (Session["IsLoggedIn"] == "true")
{
Application.Lock();
Application["UsersLoggedIn"] = (int)Application["UsersLoggedIn"] + 1;
Application.UnLock();
}
}
and then if the session is closed it will subtract 1 from the Application["UsersLoggedIn"]. My problem is that I cant count the 'IsLoggedIn' session on session start, because it is null and hence it wont work. So now we get to my quistion, Is there anyway to trigger the count of that application variable? Like to create an event when that session is true and then tell the application to add +1 to the counter on that event? Im sorry if my quistion wasnt clear, Please ask me for more deatils if its not clear and you just had no idea what i want from you.
Thank you for your help!

Dirty, hacky, inefficient, solution (assumes use of forms authentication):
public void Global_BeginRequest(object sender, EventArgs e)
{
if(
Context.User != null &&
!String.IsNullOrWhiteSpace(Context.User.Identity.Name) &&
Context.Session != null &&
Context.Session["IAMTRACKED"] == null
)
{
Context.Session["IAMTRACKED"] = new object();
Application.Lock();
Application["UsersLoggedIn"] = Application["UsersLoggedIn"] + 1;
Application.UnLock();
}
}
At a high level, this works by, on every request, checking if the user is logged in and, if so, tags the user as logged in and increments the login. This assumes users cannot log out (if they can, you can add a similar test for users who are logged out and tracked).
This is a horrible way to solve your problem, but it's a working proto-type which demonstrates that your problem is solvable.
Note that this understates logins substantially after an application recycle; logins are much longer term than sessions.

I think the session items are client sided.
You can create a query to count the open connections (hence you're working with a MySQL database.)
Another option is to use external software (I use the tawk.to helpchat, which shows the amount of users visiting a page in realtime).
You could maybe use that, making the supportchat invisible, and only putting it on paging which are accesible for loggedin users.
OR
Execute an update query which adds/substracts from a column in your database (using the onStart and OnEnd hooks).

That is the problem that you cannot do it using Session[] variables. You need to be using a database (or a central data source to store the total number of active users). For example, you can see in your application, when the application starts there is no Application["UsersOnline"] variable, you create it at the very instance. That is why, each time the application is started, the variable is initialized with a new value; always 1.
You can create a separate table for your application, and inside it you can then create a column to contain OnlineUsers value. Which can be then incremented each time the app start event is triggered.
public void Session_OnStart()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
// At this position, execute an SQL command to update the value
Application.UnLock();
}
Otherwise, for every user the session variable would have a new value, and you would not be able to accomplish this. Session variables were never designed for such purpose, you can access the variables, but you cannot rely on them for such a task. You can get more guidance about SQL commands in .NET framework, from MSDN's SqlClient namespace library.

Perhaps I am missing something, but why not something like this:
public void Session_OnStart()
{
Application.Lock();
if (Application["UsersOnline"] == null )
{
Application["UsersOnline"] = 0
}
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}

Maybe I'm missing something, but is there a reason you don't just want to use something like Google Analytics?
Unless you're looking for more queryable data, in which case I'd suggest what others have; store the login count to a data store. Just keep in mind you also have to have something to decrement that counter when the user either logs out or their session times out.

Try this. It may help you.
void Application_Start(object sender, EventArgs e)
{
Application["cnt"] = 0;
Application["onlineusers"] = 0;
// Code that runs on application startup
}
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["cnt"] = (int)Application["cnt"] + 1;
if(Session["username"] != null)
{
Application["onlineusers"] = (int)Application["onlineusers"] + 1;
}
else
{
Application["onlineusers"] = (int)Application["onlineusers"] - 1;
}
Application.UnLock();
// Code that runs when a new session is started
}
now you can display the number of users(Without Loggedin):
<%=Application["cnt"].ToString()%>
and number of online users:
<%=Application["onlineusers"].ToString()%>

Related

Storing value from try for use in second try C#

Good day fellow helpers, i have following problem:
(running MS Visual Community Edition 2015)
private void button4_Click(object sender, EventArgs e) // Senden
{
serialPort2.WriteLine("SR,00,002\r\n");
textBox1.Text = "gesendet";
textBox3.Text = "";
try
{
System.IO.StreamReader file = new System.IO.StreamReader("C:\\blub.txt");
String line = file.ReadToEnd();
string Hallo = line; \\in the beginning there is "0" in the file
file.Close();
decimal counter = Convert.ToDecimal(Hallo); \\just for testing
counter++;
string b = serialPort2.ReadLine();
string[] b1 = Regex.Split(b, "SR,00,002,"); \\cuts off unwanted input from device
decimal b2 = decimal.Parse(b1[1]); \\number like -3000
System.IO.StreamWriter test = new System.IO.StreamWriter("C:\\blub.txt");
test.WriteLine(counter);
test.Close();
textBox7.Text = "Das ist counter:" + counter;
}
catch (TimeoutException)
{
textBox3.Text = "Timeout";
throw;
}
}
Now, the Serialport is a device that returns a lengthmeasurment. As it is a bit weird, or just the way its build it start with a negitve number (between -5000 and -3370). Now as i want to get measurement on the screen that is realistic i want to set the value to 0 and calculate the difference.
Means: I start the programm - press send - get a value (say -3000) - press send again (after pushing the seonsor in) and get the value that its been pushed in > 0 by adding the difference to 0.
I only learned to store values externally when i had a C course a year back like i did within my programm. Is there a way to store the value from the first measurement in the programm so i can use it on the next send/try?
The counter was just for testing and I would exchange it for the "decimal b2"
I hope there is an easy fix for that, not really a pro with C# yet but i'm eager to learn. I thank the willing helpers in advance, MfG, Chris
OK, I will simplify this in order to show concept so it will not have all the code you are actually using.
So, what you want is to click on button, get some values and store them for next click.
Value is stored in variable. If you have variable in function that is handler for click event, as soon as function completes execution, value will be destroyed.
So, what you need is to create variable in outer scope (class level). Your function is already in class of the form so let's get to code:
class Form1
{
string BetweenClickStorage;
private void button4_Click(object sender, EventArgs e)
{
//Load data here
BetweenClickStorage = LoadedData;
}
}
After this, when you click again on the button, value will still be in BetweenClickStorage. It will be also available to all other buttons click handlers and other code in that form.
If I'm understanding your question correctly, the answer is simply to declare a variable outside the try/catch:
//declare variable //
var measurement;
// TRY #1 //
try
{
//assign value to the variable here
}
catch
{
}
// TRY #2 //
try
{
// reference variable here
}
catch
{
}

Why is list emptying itself between events?

I'm using a List<> as a container for some data returned from database, like this:
List<BookInfo> result {get;set;}
protected void SearchButton_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
result = (new BookInfo()).Search(TextBox1.Text);
ListView1.DataSource = result;
ListView1.DataBind();
}
}
Everything works ok. But when I'm trying to sort this List in other event like this one, it's empty.
protected void ListView1_Sorting(object sender, ListViewSortEventArgs e)
{
IComparer<BookInfo> comparer = new BookInfoOrdering();
if (result != null)
{
result.Sort(comparer);
}
ListView1.DataSource = result;
ListView1.DataBind();
}
I'd just like to know why is it happening. One solution is to call the search method and get the data again but isn't it unnecessary?
You were trapped by the same trap that many people are trapped by many times - it's the page lifecycle. ASP.NET fools you by pretending that you had one environment including server and browser, but that's not the case. HTTP is state-less. If you need to persist state between two requests, you have several options:
Serialize the state into the so-called ViewState such as to send it to the browser and post it back to the server
Save it in a database
Save it in the session
Introduce caching for the data that need to be retrieved, that is, sequential calls to BookInfo.Search with equal parameter values don't issue a new database request (or whatever else is required to get the data)
This would work in a desktop application, but not a asp.net website. Server side data retrieved from one postbacks is not stored for the next postback.
There are several methods for storing data between postbacks. For example using the Session State of the website:
// storing
HttpContext.Current.Session["list"] = result;
// retrieving
List<BookInfo> temp = (List<BookInfo>)HttpContext.Current.Session["list"];
you should also be able to retrieve the list from the ListView where it was bound.
IComparer<BookInfo> comparer = new BookInfoOrdering();
List<BookInfo> temp = (List<BookInfo>)ListView1.DataSource;
temp.Sort(comparer);
ListView1.DataSource = temp;
ListView1.DataBind();

Sessions not persisting?

I'm at my wits end. My code isn't keeping track of sessions in C#
I'm using a user control which should pick up the session data, but it doesn't.
Here's the user control:
[Serializable]
public partial class studentComments : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
string currStud;
if (Session["CS"] == null)
{
currStud = "50";
}
else
{
currStud = (string)Session["CS"];
}
lblHeader.Text = "Comments for Student " + currStud;
//display(currStud);
}
}
and here is the code in the initial aspx.cs page
try
{
student temp = studList.Find(o => o.student_id == studID);
Session["CS"] = "45";
PnlComment.Visible = true;
}
catch (NullReferenceException nre)
{
lblTest.Text = "Student does not exist!";
}
Obviously the user control is in the PnlComment control.
edit
I'm actually having an object passed to the session but I changed it to a static string for testing purposes, hoping that would simplify things. Alas, the label keeps showing 50. Why isn't it showing 45?
Help?
It isn't a very widely held opinion but I've always found ASP's session management rules to be a bit counter intuitive so I tend to avoid using them at all. In addition I just don't like using strings as identifiers throughout my program as it can lead to collisions and other sorts of run time bugs.
Stick with using cookies to save your own session identifier that lives in the database and have it serialize/deserialize to an object with properties and fields. It's much more resilient to refactoring and if something goes wrong it's a lot easier to debug.
Your default.aspx.cs page_load event is firing after the user control page_load event, so while the session value might be "45" after the page is loaded, the header text value will show the old value of "50" because it was set before then.

Prevent multiple running of a server side method

I have a webpage with a button that does postback, connects to an external database to download some data and perform some database updates. The issue I have is the possibility that two or more people runs this download simultaneously or while the function is still running, which may cause problems.
How do I create some form of semaphore so that if the second person clicks the button, he'll get a message saying it's currently being updated?
Use a proper transaction on your external database and apply row locking there as needed; the DB system should handle the concurrency just fine.
At the first sight, I would use an ASP.NET Application variable enclosed in a lock statement to check and update it if needed.
protected void Page_Load(object sender, EventArgs e)
{
if (!GetSem_SomeoneIsDownloading())
{
PerformDownload();
ClearSem_SomeoneIsDownloading();
}
else
{
DisplayMessageSomeoneIsDownloadingAlready();
}
}
bool GetSem_SomeoneIsDownloading()
{
bool isSomeoneDownloading;
Application.Lock();
isSomeoneDownloading = (bool)(Application["SomeoneIsDownloading"] ?? false);
if (!isSomeoneDownloading)
Application["SomeoneIsDownloading"] = true;
Application.UnLock();
return isSomeoneDownloading;
}
void ClearSem_SomeoneIsDownloading()
{
Application.Lock();
Application["SomeoneIsDownloading"] = false;
Application.UnLock();
}

Why with some browsers i get a wrong value for my Session object?

I am coding an asian language learning module for my mojoportal-based iphone-optimized website (work in progress, english resources are not fully translated: http://ilearn.dandandin.it/kanatrainer.aspx)
It's a simple "guess how to read this" game, with the right answer stored in a Session object.
I don't understand why, but, expecially using Safari, users will get someone else's Session value
This is an excerpt from the code (i removed some stuff, translated the variables)
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
...
generateRandom();
}
}
protected void generateRandom()
{
int i, j = 0, livello = 5, chance = 0;
System.Random acaso = new Random();
...
while (j <= 0)
{
j = acaso.Next((Convert.ToInt32(TextBoxlunghezza.Text) + 1));
}
...
for (int k = 0; k < j; k++)
{
i = acaso.Next(livello);
Session["randomLetters"] += (globals.asianCharacters[i]);
...
}
...
}
protected void AnswerButton_Click(object sender, EventArgs e)
{
string compare = Server.HtmlEncode(InputTextBox.Text.ToLower());
if (compare == "")
{
Label1.Text = ("You did not write anything");
return;
}
if (Session["randomLetters"].ToString() != compare)
{
Label1.Text = ("Wrong!" + Session["randomLetters"]);
}
else
{
Label1.Text = ("Right!" + Session["randomLetters"]);
}
...
}
What happens in visual studio, with every browser:
randomLetters is "hello". User writes "hello" in the textbox, and "hello" is compared to "hello". Label says "Right! hello".
What happens in iis, only in webkit-based browsers:
randomLetters is "hello". User writes "hello" in the textbox, but "hello" is compared to "goodbye". Label says "Wrong! goodbye".
I don't understand how Session["randomLetters"] has changed
Public vs private code:
How are your storing the session state? Cookie? Database? so on... I have had many problems (usually with IE 8) with the way that the browser was caching the pages and the cookies. Usually, changing the respective setting in the browser fixed the problem. I don't know if that helps here. To make it more robust, I then have to find a way to notify the user when one of these settings is not right.
Using HiddenFields i "solved" the problem (but i don't like that way)

Categories

Resources