I have a class level price variable decalred inside a page, like this:
public partial class _Default : System.Web.UI.Page
{
private MyClass myVar = new MyClass();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
myVar.LoadData();
myVar.ShowData();
}
}
protected void cmdRefresh_Click(object sender, EventArgs e)
{
myVar.ShowData();
}
}
The problem I have is that after the initial load, the first time that the button is pressed it seems to reset myVar, and all its data is lost. Is this a known issue with ASP.NET and is there a workaround?
Use the ViewState to store the class, if you just need to save the classfor the current page. IF you want to save it for the entire site, then look into things like Sessions.
private MyClass myClass
{
get {
if (this.ViewState["myVar"] != null)
{
return (MyClass)this.ViewState["myVar"];
}
}
set{
this.ViewState["myVar"] = value;
}
}
The variable myVar will never be persisted across postbacks, you need to use some method of caching, such as Application / Session / ViewState / Cookies.
Yes that is a know functionality. Basically you page object is created for every request, so properties are set for you (IsPostBack being one of them) but you need to take steps you self to make sure that fields (declared in code) is populated every time. In this particular case either by fetching Them or keeping Them in the form (viewstate) or session data. Which one to choose should depend on such as size of data, time to refetch, data store loads etc.
Related
Does static variables retain their values across user sessions?
I have a ASP.NET web application where I have two buttons. One for setting the static variable value, another for Showing the static variable value.
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
public static int customerID;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ButtonSetCustomerID_Click(object sender, EventArgs e)
{
customerID = Convert.ToInt32(TextBox1.Text);
}
protected void ButtonGetCustomerID_Click(object sender, EventArgs e)
{
Label1.Text = Convert.ToString(customerID);
}
}
}
While this works in single-user environment, What happens if there are 2 users simultaneously logged in from two computers, User 1 sets the value as 100, then User 2 sets the value as 200. after that user 1 invokes the Get Value button. What will he see as the value?
Does static variables retain their values across user sessions?
Yes, that's why you should be VERY careful when you use static variables in a web app. You will run in concurrency issues as more than one thread servicing a request can modify the value of the variable.
While this works in single-user environment, What happens if there are
2 users simultaneously logged in from two computers, User 1 sets the
value as 100, then User 2 sets the value as 200. after that user 1
invokes the Get Value button. What will he see as the value?
The user will see 200 afterwards.
Static Variables Scope is Application Level.
If you store something in Static variables, definitely your doing something wrong.
If one user saves the data(In Static variable), Same time another user access same page then he will get the same data(First User saved).
So better you can store the values in **Sessions**.
This would work for you (keep in mind, you need to handle null values/-1):
public static int customerID
{
get { return session["customerID"] == null? -1 : (int)session["customerID"]; }
set { session["customerID"] = value; }
}
Do not use static for the property then it works:
public int customerID
{
get { return Session["customerID"] == null? -1 : (int)Session["customerID"]; }
set { Session["customerID"] = value; }
}
MasterPage:
public string strP;
public void Page_Load()
{
strP = #"SELECT * FROM ...";
}
Content Page:
public void Page_Load() {
if (!Page.IsPostBack) {
string strO = Master.strP; //strO = null
}
}
I know I am supposed to use the Page_Init but can someone assist me in ensuring I am able to get the set value of strP from the content page.
This is down to the page lifecycle...
The Content Page's load method will fire BEFORE the Masterpage's Load method. Slap a breakpoint in both Load event handlers and you'll see what I mean...
The Page_Load() is meant for you to do some things related to the page. You postpone some things you can't do in the constructor for the relevant objects missing (like the Request, Response, etc).
Looking at your code, setting a static SQL statement, which doesn't require any interaction with the request, etc. can be done in the constructor already.
If it is related to the request, you could put that in the Init event of the master page.
Also see my related answer on Variables from Master Page always empty.
In case others have the same questions or would like to know how to achieve what I requested, here is the detailed steps:
First assign the public variables in the MasterPage:
public string strO;
protected void Page_Init(object sender, EventArgs e)
{
strO = #""; //whatever the variable supposed to be
}
Call in Content Page:
public string strOT;
protected void Page_Init(object sender, EventArgs e)
{
strOT = Master.strO;
}
I have a variable of type List<Foo> declared on the top of my C# class in my ASP.NET project. In the load method I instanciate this class, but when I try to use this object (already instanciated in load method) in another method it is null, giving me the error ArgumentNullException.
Here's how I'm doing it:
public partial class Teste : System.Web.UI.Page
{
List<Foo> myList;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
myList = new List<Foo>();
}
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" }); //NullReferenceException - myList is null here!
}
}
It may be simple, but I'm new to web forms so I don't know what's happening here. I know that in windows forms it works just fine.
The only way I got it to work was declaring as static:
static List<Foo> myList;
But I don't think it's the right way to do it.
Any help would be appreciated.
Having it as static won't help the Null Reference Exception.
You need to understand your check if (!IsPostBack) in your Page_Load event and remember that Web is stateless.
So On your first page load, your List is instantiate. What happens next is when you click your button. Now it is a Post Back and that will cause !IsPostBack check to return false. Here one would think that the List has been instantiated previously and doesn't require instantiation again. But the web is stateless, so on a Page_Load the List has lost the contents and it is being set to null again.
You need to maintain your state. There are various ways to do it, ViewState, Session and cookies come to mind. Read about them and use accordingly.
In your case you can do:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myList = new List<Foo>();
Session["myList"] = myList;
}
else
{
myList = Session["myList"] as List<Foo>;
}
}
and in Button Click
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" });
Session["myList"] = myList; //save it back in session
}
This will restore the original list on post back. But remember Sessions are expensive as they are maintained per user on the server.
You can also use ViewState but that will require a Serializable object.
To make a class Serializable see: Basic Serialization - MSDN
[Serializable]
class Foo
{
public int ID { get; set;}
public string Name {get; set;}
}
and then you can use ViewState instead of Session in the above code . The advantage of ViewState is that it will be maintained page wise on client side and there will be no burden on server like in case of Session. So your code with ViewState would be like:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myList = new List<Foo>();
ViewState["myList"] = myList;
}
else
{
myList = ViewState["myList"] as List<Foo>;
}
}
and for Button click:
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" });
ViewState["myList"] = myList; //save it back in session
}
You may see: ASP.NET State Management Recommendations
You only instantiate when !IsPostBack. The button click event is a postback. You need to rework your logic based on what you are trying to accomplish. What is stored in the List<Foo>? Consider placing the object in Session Cache if you intend to use repeatedly or on multiple pages.
You have to initialize all variables at every postback because all variables (and controls) are disposed at the end of the page's lifecycle, so after it was rendered and sent to the client.
So replace
if (!IsPostBack)
myList = new List<Foo>();
with
myList = new List<Foo>();
You should also not use static fields in ASP.NET since they are shared acrosss all requests. That means every user has the same list.
If you want to retain the list across postback you could use the Session. But i advise against this. Why do you need to store it in server memory at all? If you need to use it as DataSource for a web-databound control like Repeater or GridView you don't need to store it. Just let the ViewState restore the state of the controls. That is done automatically by default.
On each PostbBack, your variable will be at null. You have to provide a way to regenerate it. If you want to do it the simple way, use the ViewState.
if (!IsPostBack)
{
myList = new List<Foo>();
ViewState["myList"] = myList;
}
else
{
myList = (List<Foo>)ViewState["myList"];
}
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" }); //NullReferenceException - myList is null here!
ViewState["myList"] = myList;
}
common class file common.cs: This file, I have added by clicking add->new items-> class
public class common
{
public int v,n;
public int da()
{
return n= v;
}
}
Another file: It's an webpage file name is a1.aspx.cs:
common c = new common();
c.v = Convert.ToInt32(TextBox1.Text);
c.da();
Response.Redirect("ulogin.aspx");
the value from a text box stores in c.v variable
So, now, I want the value which was given in the textbox1.text in another webpage file named as ulogin.aspx.cs
I used this code:
common d=new common();
d.da();
Label1.Text = Convert.ToString(d.n);
but after running it shows the value as 0.....
In a web application, you'll need to persist the information somewhere common (typically Session for per user info or Application for per application info) so that it can be used between different pages & user controls in your application.
I'd suggest adding a Session backed property to your page & usercontrol which accesses a common Session["variable"]. Something like the following.
(i.e. lets imagine your code was being exectued on a button click)
a1.aspx.cs
public int ValueToStore
{
get
{
return Session["ValueToStore"] != null
? (int)Session["ValueToStore"]
: 0
}
set
{
Session["ValueToStore"] = value;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
ValueToStore = Convert.ToInt32(TextBox1.Text);
Response.Redirect("ulogin.aspx");
}
ulogin.aspx.cs
public int ValueToStore
{
get
{
return Session["ValueToStore"] != null
? (int)Session["ValueToStore"]
: 0
}
set
{
Session["ValueToStore"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = ValueToStore.ToString();
}
As you can see, you now have some code duplication between the two pages, so the next step would be to consider implementing a basepage which as the common property, and then inherit that from a1.aspx & ulogin.aspx.
i.e.
public class a1 : BasePage
{
...
}
public class ulogin : BasePage
{
...
}
public class BasePage : System.Web.Page
{
//Put ValueToStore property here.
}
There are many users visiting same page, they may set different value, and the expected result is whatever value is set by an user on Page 1 need to be displayed in Page 2.
Any Web technology is stateless as they use HTTP which is stateless again.
However there are many ways to get this done, each method has their own advantages.
--Session--
Please use session variable to store your value, which is a kind of variable.
Each user has different session variable to store, and its available
Until the user logs out (i.e. till Session is available)
Storage: Server Memory
public class Common
{
public int? Data
{
get
{
if(Session["Data"]!=null)
{
return int.Parse(Session["Data"].ToString());
}
return null.
}
set
{
Session["Data"]=value;
}
}
}
--Query String--
You can pass value from one page to another page using query string.
Page 1
int value=1;
Response.Redirect("Page2.aspx?data="+value.ToString())
Page 2
if(!string.IsNullOrEmpty(Request["data"]))
{
int value=int.Parse(Request["data"]);
}
--Posting--
You can also post the value from one page to another page.
Page 1 (html)
<form action="page2.aspx" method="post">
<input type="hidden" name="data" value="1"/>
</form>
Page 2
if(!string.IsNullOrEmpty(Request["data"]))
{
int value=int.Parse(Request["data"]);
}
There are even more ways... You have to select what is suitable for your scenario.
Read ASP.NET State management
http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx
If the page ulogin.aspx is designed to be always redirected from a1.aspx, then set the PreviousPageType in ulogin.aspx and get the previous page values by this.PreviousPage instance. (Cross-Page-PostBack)
Convert member v to a property of common. Store common into a Session variable. And once you are ready to get the value, cast session variable to common and access v property from there.
I am using devexpress controls in my page, but that is not the problem.
Here is what happens, I have created a property in the page with a get only, this property will retrieve query string value from a ViewState. I store the value in the ViewState on page load event which is enclosed in !IsPostBack. After I store
note that i have put an update panel on my master page.
I searched the net and found that ViewState values are never stored in callbacks, I don't know if that is the reason. Here is my code:
public partial class _Default : BasePage
{
private Int64 RequestId
{
get
{
return (Int64.Parse(ViewState["RequestId"].ToString()));
}
}
protected override void Page_Load(object sender, EventArgs e)
{
//Check for security
base.Page_Load(sender, e);
if (!IsPostBack)
{
GetQueryString();
gridBind();
}
}
private void GetQueryString()
{
string requestId = this.Request.QueryString["RID"];
if(!String.IsNullOrEmpty(requestId))
ViewState["RequestId"] = Int64.Parse(this.Server.UrlDecode(requestId))
else
ViewState["RequestId"] = 0;
}
}
I edited the question, the first problem i had was due to the IE7 stupidity, but nevertheless ViewState after each postback is null. I tried to use the EnableViewState but it's always null. It's the same in any page I use in my solution. We can't use ViewStates at all. There is definitely something wrong.