In the below code I am getting a Null Reference Exception error while using "Names.Add(string)" method. But when I use a static class or a static object of the NamedDB class it works fine. Can any one explain how object instances work in ASP.Net web applications ? Why am I getting errors in nonstatic objects while static objects are working fine ?
public partial class _Default : System.Web.UI.Page
{
NameDB Names; //Creating Object
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Names = new NameDB();//Instantiation
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Names.Add("dss");//Object Reference is null
GridView1.DataSource = Names.GetName();
GridView1.DataBind();
}
}
//NamedDB class
public class NameDB
{
List<string> Names=new List<string>();
public void Add(string item)
{
Names.Add(item);
}
public string Remove(string item)
{
Names.Remove(item);
return item;
}
public List<string> GetName()
{
return Names;
}
}
You do not have instances of global object which are instantiated before post back. Instantiate the object again in Button1_Click
Now You would be expecting the collection to hold data between post back but you wont get it until you store it some where like database, files,session, viewstate or cache for data. Session and ViewState are not meant for storing that type of data though.
protected void Button1_Click(object sender, EventArgs e)
{
Names = new NameDB();//Instantiation
Names.Add("dss");//Object Reference is null
GridView1.DataSource = Names.GetName();
GridView1.DataBind();
}
Replace this:
NameDB Names; //Creating Object
by this
NameDB Names = new NameDB(); //Creating Object
You can do any of following
public partial class _Default : System.Web.UI.Page
{
NameDB Names= new NameDB();//Creating Object
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Names.Add("dss");
GridView1.DataSource = Names.GetName();
GridView1.DataBind();
}
}
or
public partial class _Default : System.Web.UI.Page
{
NameDB Names;//Creating Object
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Names = new NameDB();//Instantiation
Names.Add("dss");
GridView1.DataSource = Names.GetName();
GridView1.DataBind();
}
}
The problem is that the page-object is recreated for every request. So page-level fields are re-initialized for every call. And a postback is just another request!
If you want to persist values between requests, you need to find some way to store these.
Some options are:
In a real database, takes some work but you have full control and full persistence
In Cache or Application, for application-wide storage where every visitor gets the same values, but these are lost when the app recycles.
In Session, for user-specific storage as long as the session doesn't time out (and the app doesn't recycle)
In ViewState, for "postback-specific" storage: this will keep values through postbacks to the same page (user-specific), but are lost when the user goes to another page.
Related
I have a web service which contains 2 methods, one of them is for getting user name and password, and the second is method which I need to send it 3 suppliers and gets their gain.
For doing that, I need to use the first method data, and send it to the second method... but I don't know how to do it.
Below is the code that I wrote, the first code is to get the user name and password by clicking on a button, and the second is used for sending the data to the second method.
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(Object sender, EventArgs e)
{
webService.TestService test = new webService.TestService();
string result = test.GetUsernameAndPassword();
Label1.Text = result.ToString();
}
protected void Button2_Click(Object sender, EventArgs e)
{
}
}
}
If it is okay to use Sessions, in Button1_Click add the result to Session and in Button2_Click access result from Session. Sample code is given below.
Note: You can store any serializable data in Session, unless you use inproc session manageemnt.
protected void Button1_Click(Object sender, EventArgs e)
{
webService.TestService test = new webService.TestService();
string result = test.GetUsernameAndPassword();
Label1.Text = result.ToString();
Session.Add("UsernamePassword", result);
}
protected void Button2_Click(Object sender, EventArgs e)
{
string usernamePassword = Session["UsernamePassword"] as string;
}
Without using Session variables or static classes, is it possible to instantiate a class that's available to all the event handlers in one webform?
For example, my code looks like this. I instantiate Car and set property Color in Page_Load. I know I can't access it from another event handler.
I prefer not using session variables since they tend to expire, and the users here tend to go to a page and then leave it open for a while. I could always set the session's timeout, but I prefer something that lasts throughout the page's life cycle.
namespace MyNamespace
{
public partial class ToErase : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Car myCar = new Car();
myCar.Color = "Black";
}
protected void Button1_Click(object sender, EventArgs e)
{
//Have access to myCar.Color here;
//Response.Write(myCar.Color);
}
}
public class Car
{
public string Color { get; set; }
}
}
If your question is about persistence then in WebForms, ViewState comes to mind (for above).
Depending on use case, at the end of the day, you could involve the client more, with client-based persistence (e.g. DOM storage, etc.). At the end of the day, events like click occur on the client-side...ASP.Net sort of abstracts much of that for you. If you checked the source of your WebForms page, you'll see all that Javascript that does the "magic" for you.
Hth...
You can define it as below and then you would be able to access it :-
public partial class ToErase : System.Web.UI.Page
{
private Car myCar;
protected void Page_Load(object sender, EventArgs e)
{
this.myCar = new Car();
this.myCar.Color = "Black";
}
protected void Button1_Click(object sender, EventArgs e)
{
this.myCar.Color = "Blue"; ////You can access it here
//Have access to myCar.Color here;
Response.Write(this.myCar.Color);
}
}
public class Car
{
public string Color { get; set; }
}
Am i missing someting ? Just with
public partial class ToErase : System.Web.UI.Page
{
private Car myCar;
protected void Page_Load(object sender, EventArgs e)
{....}
}
I have a simple button:
<asp:Button ID="mybtn" runat="server" Text="My Btn" onclick="mybtn_Click" />
And code behind:
protected MyCustomObject myObject;
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
this.myObject = new MyCustomObject();
}
}
protected void mybtn_Click(object sender, EventArgs e)
{
this.myObject.step(1);
}
protected void anotherbtn_Click(object sender, EventArgs e)
{
this.myObject.step(2);
}
The problem: when click, the Page_Load is called and this.myObject is null.
The goal is to call anotherbtn_Click after call mybtn_Click with the same object instance.
How to keep object's context?
You can not assume that an instance of the Page class is kept for each "user"; therefore you can not use class variables as in your example. In order to store information across multiple requests, you can use the Session Context. See the following link for more information: http://msdn.microsoft.com/en-us/library/ms178581%28v=vs.100%29.aspx
In your case you could store the MyCustomObject instance in the session state. Example
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
Session["MyObject"] = new MyCustomObject();
}
}
protected void mybtn_Click(object sender, EventArgs e)
{
MyCustomObject myObject = Session["MyObject"] as MyCustomObject;
myObject.step(1);
}
protected void anotherbtn_Click(object sender, EventArgs e)
{
MyCustomObject myObject = Session["MyObject"] as MyCustomObject;
myObject.step(2);
}
The web is stateless. You always needs to create a new object for every request/post.
This means when every time your page is accessed , the new page instance will be created and served for it.
There are few ways you can solve your problem by using Session or serialize the object and keep it in ViewState
if (!IsPostBack)
{
this.myObject = new MyCustomObject();
Sesssion["oldObject"]=this.myObject;
}
protected void mybtn_Click(object sender, EventArgs e)
{
if(session["oldObject"]!=null)
{
this.myObject=session["oldObject"] as MyCustomObject;
this.myObject.step(1);
}
}
protected void anotherbtn_Click(object sender, EventArgs e)
{
if(session["oldObject"]!=null)
{
this.myObject=session["oldObject"] as MyCustomObject;
this.myObject.step(2);
}
}
this.myObject is null because you explicitly do not recreate it in Page_Load on postback.
Depending on your needs, you can either
remove the if (!IsPostBack) check so that a new instance is created on each load; or
put the instance in the session after it is created if you need to keep the same instance around between postbacks.
I have searched extensively on this, but cannot find the solution to my problem. I am trying to call a function in the code behind of a page from a user control on that page.
I have a web application that uses a master page. I am adding a user control that I wrote to one of the content pages. I added the user control to the aspx page by dragging and dropping it from the toolbox. I am able to see the user control from the code behind, but I cannot access the public functions. To fix that problem, I created an object of the user control in the code behind and used the LoadControl function. All of that seems to work fine.
The problem I am having is when I am trying to hook the into the EventHandler from the aspx page to the user control. Everything compiles and runs just fine, but I am not seeing anything happen on the page. I think the issue is that the EventHandler is always null.
User Control Code
public partial class ucBuyerList : System.Web.UI.UserControl
{
public delegate void BuyerSelectedEventHandler(object sender, EventArgs e);
public event BuyerSelectedEventHandler BuyerSelected;
private string name = "";
public string Name
{
get { return name; }
set { name = value; }
}
private string auid = "";
public string AUID
{
get { return auid; }
set { auid = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
private void OnBuyerSelected(EventArgs e)
{
if (BuyerSelected != null)
{
BuyerSelected(this, new EventArgs());
}
}
protected void lbBuyerList_SelectedIndexChanged(object sender, EventArgs e)
{
SetNameAndAUID();
OnBuyerSelected(e);
}
private void SetNameAndAUID()
{
name = lbBuyerList.SelectedItem.Text;
auid = lbBuyerList.SelectedItem.Value;
}
}
Parent Page Code
public partial class frmBuyerInformation : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Master.changePageTitle("Buyer Information");
buyerList.BuyerSelected += new ucBuyerList.BuyerSelectedEventHandler(buyerListControl_BuyerSelected);
}
void buyerListControl_BuyerSelected(object sender, EventArgs e)
{
DisplayBuyerInformation();
}
public void DisplayBuyerInformation()
{
tbName.Text = buyerList.Name;
tbAUID.Text = buyerList.AUID;
}
}
Can anyone see what I am doing wrong?
EDIT: This issue has been resolved. The code snippits above are now functional. If anyone runs into the issue I had, you can model the code above. Make sure that AutoEventWireup="true" in both the aspx and ascx pages. Thank you June Paik for your solution. Thank you Diego De Vita for your input as well.
I've been struggling with events for quite a while as well. Nowadays I always create them this way 'cause it's the only way I know it works. Haven't tested it with your code but here it goes anyway:
public partial class ucBuyerList : System.Web.UI.UserControl
{
public delegate void BuyerSelectedEventHandler(object sender, EventArgs e);
public event BuyerSelectedEventHandler BuyerSelected;
public string Name;
public string AUID;
protected void Page_Load(object sender, EventArgs e)
{
//Select the first buyer in the list when the user control loads
if (!IsPostBack)
{
lbBuyerList.SelectedIndex = 0;
}
}
private void OnBuyerSelected(EventArgs e)
{
BuyerSelectedEventHandler handler = BuyerSelected;
if (handler != null)
{
handler(this, new EventArgs());
}
}
protected void lbBuyerList_SelectedIndexChanged(object sender, EventArgs e)
{
Name = lbBuyerList.SelectedItem.Text;
AUID = lbBuyerList.SelectedItem.Value;
OnBuyerSelected(e);
}
}
In the parent page you can just call your function the same way you're doing it already.
It could be that Page_Load is too late in the page lifecycle to be using LoadControl and subscribing to the event. What happens if you move that code to the Page_Init method?
I have an application that's instantiates an object from a class called "SecretNumber" when a get of the page is done. After that, I want to work with the object that's instantiated instead of instantiating a new one.
Below is a piece of my code from the code behind-file, and the problem is that I can't use the object reference inside the button function. I get an error telling that the name doesn't exist in the current context.
How can this be solved? Thanks in advance!
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {
SecretNumber guessNr = new SecretNumber();
}
protected void btnCheckNr_Click(object sender, EventArgs e) {
if (!Page.IsValid) {
return;
}
else {
var guessedNr = int.Parse(inputBox.Text);
var result = guessNr.MakeGuess(guessedNr); <- The name 'guessNr' does not exist in the current context
}
}
}
Move declaration of the variable out of the scope of the method, so it becomes a private field of the type _Default.
This shall work
public partial class _Default : System.Web.UI.Page
{
private SecretNumber guessNr;
protected void Page_Load(object sender, EventArgs e) {
guessNr = new SecretNumber();
}
protected void btnCheckNr_Click(object sender, EventArgs e) {
if (!Page.IsValid) {
return;
}
else {
var guessedNr = int.Parse(inputBox.Text);
var result = guessNr.MakeGuess(guessedNr); <- The name 'guessNr' does not exist in the current context
}
}
}
SecretNumber guessNr = new SecretNumber();
Isn't actually doing anything. You need:
public partial class _Default : System.Web.UI.Page
{
private SecretNumber guessNr;
protected void Page_Load(object sender, EventArgs e) {
this.guessNr = new SecretNumber();
}
protected void btnCheckNr_Click(object sender, EventArgs e) {
if (!Page.IsValid) {
return;
}
else {
var guessedNr = int.Parse(inputBox.Text);
var result = this.guessNr.MakeGuess(guessedNr);
// Now use result
}
}
}
Put guessNr outside of Page_Load if you want to access it in btnCheckNr.
SecretNumber guessNr;
and then assign it in Page_Load Method.
I assume that you need to read some basic info about classes in C# (fields, methods, events). This isn't an ASP.NET problem because ASP.NET follows exactly the same paradigm as any other .NET technology in terms of OOP.
Obviously you need to use the field of type SecretNumber here