I'm new to ASP.NET :) and I'd like to understand more about session. Here's a simple example: Every time I click the button it will add one more integer to listInt and I store the list using Session["listInt"].
public partial class TestSession : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["listInt"] == null)
{
Session["listInt"] = new List<Int16>();
}
}
}
protected void AddInt_Click(object sender, EventArgs e)
{
Int16 i = 0;
List<Int16> listInt = (List<Int16>)Session["listInt"];
listInt.Add(i);
Session["listInt"] = listInt;
Response.Write("Hello!");
}
}
Here's the thing I don't understand, if I comment the line Session["listInt"] = listInt;, whenever I click the variable Session["listInt"] still store the value (means still add more integer to the list):
Int16 i = 0;
List<Int16> listInt = (List<Int16>)Session["listInt"];
listInt.Add(i);
//Session["listInt"] = listInt; //No idea why....
Response.Write("Hello!");
Can anyone please tell me how session works in this case? Thanks in advance :)
Your list is a reference type, so when you retrieve it from the server via the session state container you actually get a reference to some object in the server memory. Hence no need to reassign it later.
Related
Im trying to get an int[] array but it's returning an error which is Value cannot be null. I'm still a newbie to c#. Can someone help or give a clue how to solve this? I tried many techniques of passing the value but still no luck.
here's where the array came from
private void btnTag_Click(object sender, EventArgs e)
{
List<int> employee_id_list = new List<int>();
foreach (Control c in panelEmployee.Controls)
{
if (c is CheckBox)
{
if (((CheckBox)c).Checked)
{
employee_id_list.Add(Convert.ToInt32(c.Tag));
}
}
}
var type = Type.GetType("Payroll." + dynamic_form);
dynamic form = Activator.CreateInstance(type) as Form;
form.GetEmployeeID(employee_id_list.ToArray());
this.Close();
}
here's where i displayed it
public int[] emp_id;
public void GetEmployeeID(int[] employee_id)
{
emp_id = employee_id;
//in this code there are no errors and it is showing the array
MessageBox.Show(string.Join(Environment.NewLine, emp_id));
}
private void btnSave_Click(object sender, EventArgs e)
{
// but when i trigger this it returns and error Value cannot be null
MessageBox.Show(string.Join(Environment.NewLine, emp_id));
}
I think your problem is that you lose the value of the variable emp_id between the GetEmployee call (it assigns value to emp_id from the parameter so it will work always you pass a not null value) and the later call to btnSave_Clickthat is trying to use the previously( and hopefully) assigned value of emp_id
Maybe you are using WebForms , in that case you should assign the emp_id to a Session state or something that won't get deleted on next request.
public int[] emp_id;
public void GetEmployeeID(int[] employee_id)
{
emp_id = employee_id;
//in this code there are no errors and it is showing the array
MessageBox.Show(string.Join(Environment.NewLine, emp_id));
}
private void btnSave_Click(object sender, EventArgs e)
{
// but when i trigger this it returns and error Value cannot be null
MessageBox.Show(string.Join(Environment.NewLine, emp_id));
}
I've just started learning ASP.NET and I'm facing a problem with getting textbox values. I want to do a simple calculator with only 4 basic operations but what happens is that after I click the + sign and click Go, I see that I didn't store the first number at all. Second number is fine though. Here is a sample of my code.
public partial class deafult : System.Web.UI.Page
{
public TextBox output = new TextBox();
public double temp,tempAdd, calc;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnAdd_Click(object sender, EventArgs e)
{
tempAdd = Convert.ToDouble(output.Text);
output.Text = String.Empty;
}
//User enters another number after clicking Add button then clicks Proc
protected void proc_Click(object sender, EventArgs e)
{
temp = Convert.ToDouble(output.Text);
calc = tempAdd + temp;
output.Text = calc.ToString();
}
}
I debugged and tempAdd is always 0 but I get the number in temp. temp variables and calc is defined public.
You essentially have the problem with all of your variables being re-initialized on load of the page. Unlike winforms, web is stateless.
There are ways of persisting state between refreshes, however. The most obvious choice for your application would be to only go to the server once with the both values and what you want to do with them. ie One button click.
However, for personal edification, it may be worth looking up ViewState. This allows you to store values in an array of sorts and retrieve them even after a refresh.
There are also Session and Application level arrays in ASP.NET that work in similar ways.
Every time you call the page (by events) all your properties is initialized.
Try to do all your logic in one event or store your properties in manager / service / db.
In web (Asp.Net) on every postback properties will get cleared, try to use ViewState or Session variables to hold these values. Refer Asp.Net State Management concepts from MS.
Hope this may help you.
Web controls are State less so you should user session sate to hold the first value then do your stuff...
Ex:-
protected void btnAdd_Click(object sender, EventArgs e)
{
Session["tempAdd"] = output.Text;
output.Text = String.Empty;
}
protected void proc_Click(object sender, EventArgs e)
{
temp = Convert.ToDouble(output.Text);
string oldval=Session["tempAdd"] != null ?Session["tempAdd"].ToString() :"";
if(oldval!="")
tempadd=Convert.ToDouble(oldval);
calc = tempAdd + temp;
output.Text = calc.ToString();
}
Whenever i click on the Button1 repeatedly then text in the Literal1 is not incremented. Can you please tell me reason?
Expected: value show in text field increment after every button click.
Current result: value always shows 1.
public partial class d1 : System.Web.UI.Page
{
int c;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
c = 1;
Literal1.Text = c.ToString();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
c=c+1;
Literal1.Text = c.ToString();
}
}
The reason is that c is an instance variable on that class. And each post-back to the server creates a new instance of the class. So c is being initialized to 0 on each post-back. If you want c to persist outside of a single instance of that class, you need to store it somewhere. Session, application, a database, etc. (Specifically where depends on under what circumstances the value of c should persist. I'm guessing this is just test code to get a feel for the functionality, so you might try all of the above and see how they differ.)
For a lot more information on this, you'll want to read up on the ASP.NET Page Life Cycle.
Essentially, "global" doesn't describe c very accurately as a variable. It's scope is very limited to only that class, and more specifically only to any one instance of that class.
So i have the code..
int var1 = 0;
protected void cmdvar1_Click(object sender, EventArgs e)
{
var1= var1+ 10;
lblvar1.Text = var1.ToString();
}
And when clicking this, its great.. it takes the int, adds 10 to it, then displays it.. however it won't display any more than 10, did some playing around and came to the conclusion, that its not because the label isnt updating, it just simply isnt adding 10 to the previous 10 on the variable. What am i doing wrong? What am I mising? Do i need to store the variable info in a cookie or something?
This is due to the lifecycle of ASP.NET. Storing private fields behind the web page isn't the same as how it works with WinForms. If you want to persist information across post backs you need to store it in some persistent storage i.e. Session/ViewState/Database etc.
private int var1 = 0;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// load var1 from cache
Int32.TryParse((Session["var1"] ?? 0).ToString(), out var1);
}
}
protected void cmdvar1_Click(object sender, EventArgs e)
{
var1 += 10;
Session["var1"] = var1; // cache var1
lblvar1.Text = var1.ToString();
}
So I would strongly suggest looking into a different platform. Perhaps ASP.NET MVC... However you can use something like the following to get arround your problem.
private int MyNum
{
get{ return (int)ViewState["MyNum"] ?? 0; }
set { ViewState["MyNum"] = value; }
}
Then just use MyNum as your integer your incrementing.
Assuming that lblvar1 is a Label control then you can do the following. The reason this will work is because .NET automatically take care of the state of UIControl
protected void cmdvar1_Click(object sender, EventArgs e)
{
var var1 = Convert.ToInt32(lblvar1.Text);
var1= var1+ 10;
lblvar1.Text = var1.ToString();
}
As suggested in the comments, you have to wrap your universe around statelessness before you will get to producing meaningful web applications.
The ASP.NET equivalent to accomplish state-like behavior is to use the Session collection which is available to every web page.
protected void cmdvar1_Click(object sender, EventArgs e)
{
int var1 = (int)Session["yourInteger"];
var1 += 10;
Session["yourInteger"] = var1;
lblvar1.Text = var1.ToString();
}
You are obviously setting an initial value for Session["yourInteger"] somewhere else, just one time.
The problem with Session is that it makes your application potentially buggy and somewhat unscalable. The more you use it, the worse on both accounts.
Use Session body, HTTP is a stateless Protocol, once you postback you loose the current variable value,
Solution:
int var1=0;
protected void cmdvar1_Click(object sender, EventArgs e)
{
if(Session["var1"]!=null)
var1=int.Parse(Session["var1"].ToString());
else
var1=0;
var1= var1+ 10;
lblvar1.Text = var1.ToString();
Session["var1"]=var1;
}
I have DataTable which feeds a dropdown list. The values of this dropdown persist when I click on the button whereas the datatable which feeds the list is null at next page reload. I need that this dataTable to also persist like its associated control so isn't there anything that asp.net has in its tricks bag to behave like for controls but for private members instead ?
public partial class _Default : System.Web.UI.Page
{
private DataTable m_DataTable = new DataTable();
private void f(String x, String y){
// some function of x,y
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
m_DataTable.Columns.Add("Title");
m_DataTable.Columns.Add("x");
m_DataTable.Columns.Add("y");
m_DataTable.Rows.Add("place1", "1", "2");
m_DataTable.Rows.Add("place2", "3", "4");
int nTotalRecords = m_DataTable.Rows.Count;
for (int i = 0; i < nTotalRecords; i++)
{
DropDownList1.Items.Add(m_DataTable.Rows[i]["Title"].ToString());
}
DataRow[] dataRowArray = m_DataTable.Select("[Title]='place1'");
String x = dataRowArray[0]["x"].ToString();
String y = dataRowArray[0]["y"].ToString();
f(x, y);
}
}
protected void ButtonGo_Click(object sender, EventArgs e)
{
// this code will crash because m_DataTable is emptied when page reloads
DataRow[] dataRowArray = m_DataTable.Select("[Title]='place2'");
String x = dataRowArray[0]["x"].ToString();
String y = dataRowArray[0]["y"].ToString();
f(x, y);
}
}
Update: I heard that asp.net paradigm was to be as close as possible as desktop. Why does it create a new instance for the page instead of keeping it ? Why does it keep the same state for controls and not for private members that is incoherent isn't it?
You can put it in view state:
Page.ViewState["DataTable"] = m_DataTable;
and retrieve it after postback:
m_DataTable = Page.ViewState["DataTable"];
The drawback is of course that the serialised data is sent to the client and back again, which increases the weight of the postback.
Another alternative is to store it in the user session:
Session("DataTable") = m_DataTable;
and retrieve it after postback:
m_DataTable = Session("DataTable");
Session.Remove("DataTable");
The drawback of that is of course that you increase the memory load on the server.
Consider the drawbacks of each method, and weight that against how much it costs to get the data again. Sometimes time is the cheapest resource.
If the data in the table does not change, don't put it inside if (!IsPostBack) {}