Unable to reuse an Object of class - c#

I am trying to create a page using object oriented design in C#. I wanted to use same instance object all the time in my page but it is not working .
Below is my code :
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SqlDataSource1.Delete();
}
}
protected void ViewBalance_Click(object sender, EventArgs e)
{
string tempString = Request.Form["BalanaceField"];
double bal;
Double.TryParse(tempString, out bal);
Session["CurrentBalance"] = bal;
BankAccount newAcc = new BankAccount(bal);
resultDiv.InnerHtml = "<h1> Current Balance is $" +
newAcc.getCurrentBalance() + "</h1>";
transactionDiv.Style["display"] = "block";
newAccountDiv.Style["display"] = "none";
}
protected void Withdraw_Click(object sender, EventArgs e)
{
string currentBal = Session["CurrentBalance"].ToString();
double bal;
Double.TryParse(currentBal, out bal);
BankAccount newAcc = new BankAccount(bal);
double withdrwaAmount;
Double.TryParse(Request.Form["WithdrawField"], out withdrwaAmount);
if (newAcc.validWithDraw(withdrwaAmount))
{
newAcc.withDraw(withdrwaAmount);
Session["CurrentBalance"] = newAcc.getCurrentBalance();
insertRecord("Withdaw", withdrwaAmount, newAcc.getCurrentBalance());
resultDiv.InnerHtml =
"<h1>Amount Withdrwan Succesfully. Current Balance is $ " +
newAcc.getCurrentBalance() + "</h1>";
}
else
{
resultDiv.InnerHtml =
"<h1>You cann't ovewdraw you account. Your current Balance is $" +
bal + " and you are trying to widthdraw $" +
withdrwaAmount + " </h1>";
}
}
protected void Deposit_Click(object sender, EventArgs e)
{
string currentBal = Session["CurrentBalance"].ToString();
double bal;
Double.TryParse(currentBal, out bal);
BankAccount newAcc = new BankAccount(bal);
double depositAmount;
Double.TryParse(Request.Form["DeopositField"], out depositAmount);
double newBalance = newAcc.deposit(depositAmount);
Session["CurrentBalance"] = newBalance;
insertRecord("Deposit", depositAmount, newAcc.getCurrentBalance());
resultDiv.InnerHtml =
"<h1>Amount Deposit Succesfully. Current Balance is $ " +
newAcc.getCurrentBalance() + "</h1>";
}
protected void InterestCount_Click(object sender, EventArgs e)
{
string currentBal = Session["CurrentBalance"].ToString();
double bal;
Double.TryParse(currentBal, out bal);
BankAccount newAcc = new BankAccount(bal);
double interestMonths;
Double.TryParse(Request.Form["MonthsField"], out interestMonths);
double interest = bal * (0.10) * (interestMonths / 12);
resultDiv.InnerHtml =
"<h1>Total amount with acculmated Interest would be $ " +
(newAcc.getCurrentBalance() + interest) +
" and Interest would be $:" + interest + "</h1>";
}
public void insertRecord(string type, double amount, double finalAMount)
{
DataView dv =
(DataView) SqlDataSource1.Select(DataSourceSelectArguments.Empty);
int id = dv.Count + 1;
SqlDataSource1.InsertParameters.Add("Id", id.ToString());
SqlDataSource1.InsertParameters.Add("Type", type);
SqlDataSource1.InsertParameters.Add("Amount", amount.ToString());
SqlDataSource1.InsertParameters.Add("Balance", finalAMount.ToString());
SqlDataSource1.Insert();
}
}
As we can see I have to always create new instance of BankAccount class in each method.
Ideally I would like just one object for entire page and reuse it when needed.

Reading your code it won't make any difference in performance. Your page is created (an object of class _Default is instantiated) with every request.
There are some possibilities:
Declare the field private or protected above your methods, at class level. But as you use this object only in Click methods you will have one BankAccount object per request, which you already have. (will not increase performance, nor reduce memory usage)
You can declare the field static, but you will have the same object for all the users on your website (you don't want someone to see a wrong balance if two requests are performed at the same time).
You can store the bank account object on session and use it, if you don't want to create it every time. (will increase memory usage, you will also use performance, as the object is serialized, deserialized and a cast must be performed)
Why do you want to do this ? Performance will not be better and the memory usage will not be optimized.

Place your definition for BankAccount newAcc just above protected void Page_Load(object sender, EventArgs e) (do some research on "scope" to understand why this works)
Inside Page_Load create your first instance
newAcc = new BankAccount(); //note that you'll want a constructor that doesn't have a balance argument
Make sure you have a public way of modifying the balance field, then when you need to change the balance:
newAcc.balance = whatever;

Related

Issue with Session Variables

So I'm trying to make a simple banking website using C# and ASP.net and I'm just learning about Session Variables for the first time. I have a starting account balance of 1000 dollars and I want to transfer that to another page and have that balance updated via withdrawals or deposits and then update the balance. Heres my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Project4.Forms
{
public partial class Services : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click1(object sender, EventArgs e)
{
double userInput = double.Parse(txtAmount.Text);
Session["userInput"] = userInput;
Session["balance"] = 1000.00;
double balance = Convert.ToDouble(Session["balance"]);
Session["userAction"] = ddlSelectService.SelectedItem.Text;
if (ddlSelectService.SelectedItem.Text == "Withdrawl")
{
balance -= userInput;
}
else if (ddlSelectService.SelectedItem.Text == "Deposit")
{
balance += userInput;
}
else
{
}
Response.Redirect("Status.aspx");
}
}
}
I understand the root of my problem is probably the original Session["balance"] = 1000.00; but I'm not sure how to declare a starting amount and then it not affect the balance when I return to this page from the results page. Any help is appreciated, also as I said in the beginning this is a barebones simple atm website please don't suggest anything too crazy because I am a beginner.
I don't do asp.net, so this is just a guess, but maybe try only setting the default value if it's null, something like: if (Session["balance"] == null) Session["balance"] = 1000;. It also seems like this should be in the Page_Load event, not the btnSubmit_Click event, since it only has to happen once.
Finally, don't forget to update the session variable after setting the new balance:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["balance"] == null) Session["balance"] = 1000;
}
protected void btnSubmit_Click1(object sender, EventArgs e)
{
double userInput;
if (!double.TryParse(txtAmount.Text, out userInput))
{
ClientScript.RegisterStartupScript(this.GetType(), "myalert",
"alert('Input must be a valid double');", true);
return;
}
Session["userInput"] = userInput;
double balance = Convert.ToDouble(Session["balance"]);
Session["userAction"] = ddlSelectService.SelectedItem.Text;
if (Session["userAction"] == "Withdrawl")
{
balance -= userInput;
}
else if (Session["userAction"] == "Deposit")
{
balance += userInput;
}
Session["balance"] = balance;
Response.Redirect("Status.aspx");
}

how to pass session value from button click to another cs file

I am trying to attempt to perform a calculation on a button click on one asp.net form (invoice.aspx) then pass it to another response (print.aspx) form and insert that value into a label. However when ever I click the submit the value ends up being 0. No errors arise when this happens. Can this be done??
The following code I have is:
print.aspx.cs
public partial class print : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DateTime date = DateTime.Now;
lblDateIssue.Text = " Date Issue:" + date.ToShortDateString();
var dueDate = date.AddDays(14);
lblDueDate.Text = " DueDate:" + dueDate.ToShortDateString();
double subTotal1 = (double)(Session["subTotal1"]);
lblItem1Ttl.Text = subTotal1.ToString();
}
}
invoice.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Session["subTotal1"] = 0.0;
}
public void btnSubmit_Click(object sender, EventArgs e)
{
int qty1 = Int32.Parse(txtQty1.Text);
double price1 = double.Parse(txtPrice1.Text);
Session["subTotal1"] = (double)Session["subTotal1"] + (price1 * qty1);
}
}
Any guidance would be appreciated
So rather than using the action attribute in the invoice.aspx form. I removed that attribute and put in Server.Transfer("print.aspx", true); to post to the response page on the button click event. I have also added the try - catch functions to stop the exception throwing. So thanks #dee-see because it was the life cycle just had to go a slightly different way to get around it. The full solution is below
invoice.aspx.cs:
public partial class invoice : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
Session["subTotal1"] = 0.0;
Session["subTotal2"] = 0.0;
Session["subTotal3"] = 0.0;
}
}
public void btnSubmit_Click(object sender, EventArgs e)
{
try
{
int qty1 = Int32.Parse(txtQty1.Text);
double price1 = double.Parse(txtPrice1.Text);
Session["subTotal1"] = (double)Session["subTotal1"] + (price1 * qty1);
}
catch
{
txtQty1.Text = "";
txtPrice1.Text = "";
}
try
{
int qty2 = Int32.Parse(txtQty2.Text);
double price2 = double.Parse(txtPrice2.Text);
Session["subTotal2"] = (double)Session["subTotal2"] + (price2 * qty2);
}
catch
{
}
try
{
int qty3 = Int32.Parse(txtQty3.Text);
double price3 = double.Parse(txtPrice3.Text);
Session["subTotal3"] = (double)Session["subTotal3"] + (price3 * qty3);
}
catch
{
txtQty3.Text = "";
txtPrice3.Text = "";
}
Server.Transfer("print.aspx", true);
}
}
print.aspx.cs:
public partial class print : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DateTime date = DateTime.Now;
lblDateIssue.Text = " Date Issue:" + date.ToShortDateString();
var dueDate = date.AddDays(14);
lblDueDate.Text = " DueDate:" + dueDate.ToShortDateString();
lblItem1Ttl.Text += "$" + (double)(Session["subTotal1"]);
lblItem2Ttl.Text += "$" + (double)(Session["subTotal2"]);
lblItem3Ttl.Text += "$" + (double)(Session["subTotal3"]);
double total = ((double)(Session["subTotal1"]) + ((double)(Session["subTotal2"])) + (double)(Session["subTotal3"]));
lblTotalAmount.Text += "$" + total;
}
}

Deleting a label that was duplicated

I have a program where a user fills in a form and hits calculate, then when the user hits summary it will show all the users that have entered in data. When more users enter data, they are simply added to the summary using the same lbl (lblUsers) the only problem I am having is being able to delete the most recent entry into the summary which would be the newest made label.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LifeInsurance
{
public partial class frmMain : Form
{
double commissionRate;
double insuranceAmount;
double totalAmount;
int numberOfCustomers;
double totalInsuranceDollars;
double totalCommission;
private void btnClearAll_Click(object sender, EventArgs e)
{
lblUsers.Text = "";
}
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
}
private void btnCalculate_Click(object sender, EventArgs e)
{
try
{
string firstName = txtFirstName.Text;
string lastName = txtLastName.Text;
insuranceAmount = int.Parse(txtInsuranceAmount.Text);
}catch (Exception)
{
MessageBox.Show("You must enter all details");
}
if(insuranceAmount>= 1000)
{
commissionRate = 0.005;
totalAmount = insuranceAmount * 0.005;
}
if (insuranceAmount >= 100000)
{
commissionRate = 0.0010;
totalAmount = insuranceAmount * 0.0010;
}
if (insuranceAmount >= 1000000)
{
commissionRate = 0.0015;
totalAmount = insuranceAmount * 0.0015;
}
totalInsuranceDollars += totalAmount;
totalCommission += commissionRate;
numberOfCustomers += 1;
lblUsers.Text += "Name: "+txtFirstName.Text +" "+ txtLastName.Text+"
"+ "Payout Amount: "+totalAmount+Environment.NewLine;
lblUsers.Text += "Total Policies: " + numberOfCustomers+" " + "Total
Insurance Dollars Earned: " + totalInsuranceDollars+" " + "Total
Commission Earned: " + totalCommission+Environment.NewLine;
}
private void btnSummary_Click(object sender, EventArgs e)
{
lblUsers.Visible = true ;
}
private void btnClear_Click(object sender, EventArgs e)
{
//remove one label
}
}
}
I'm sorry, if I understand correctly you want your Label to show all but the last entry when the user clicks "Summary" is that correct? So in your screenshot it shows 3 entries, but you want only 2 entries to be shown?
If so, see if this helps:
public static void btnSummary_Click(object sender, EventArgs e)
{
string currentText = lblUsers.Text;
int positionOfLastEntry = currentText.LastIndexOf("Name:");
string textWithoutLastEntry = currentText.Substring(0, positionOfLastEntry);
lblUsers.Text = textWithoutLastEntry;
lblUsers.Visible = true;
}

Why is my data changing when I am not changing it? [duplicate]

This question already has answers here:
When is a C# value/object copied and when is its reference copied?
(3 answers)
Closed 8 years ago.
I am working on a Microsoft Visual C# Form Application that is to be used to create all the data that would go into RPG game. I have designed a structure and encased it all into a class so I can easily read and write to/from an XML file.
On my main form I have a "public static"/"Global" variable that all of my sub forms can copy information from... manipulate what it needs to... and send that information back to it.
For example. I want multiple types of currencies. The form that deals with currencies copies only the currency data from the global variable and has free reign to manipulate only THAT copy. Only when the user clicks the "Apply" or "Accept" button should the global variable be updated to reflect those changes. If the "Cancel" button is clicked it should just close the form and the copied data should get tossed to the winds when the form is disposed.
Unfortunately this is not the case. Whenever I change the data of the copy its changes seem to reflect on the global variable as well. Is there a concept here I am missing here and don't understand. Somebody please explain. I've checked over my code and there are only those two points where the data should be updated.
Code from "Main" Form
public partial class frmMain : Form
{
public static RPGDataCollection DATA = new RPGDataCollection();
public static string FILE = "";
public frmMain ()
{
InitializeComponent();
FillDefaultData();
}
/// <summary>
/// Sets item info status text.
/// </summary>
/// <param name="text">Text to be displayed.</param>
private void SetItemInfo (string text)
{
lblItemInfo.Text = text;
}
Currency Form Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RPGData.ObjectTypes.DataGroups;
namespace RPGData.EntryForms
{
public partial class frmCurrencies : Form
{
#region Fields
private List<Currency> datCurrencies = new List<Currency>();
private string strEntry = "";
private bool blnGSC = false;
private bool blnUpperFlag = false;
private int intIndex = 0;
#endregion
#region Constructor
public frmCurrencies ()
{
InitializeComponent();
}
#endregion
#region Events
private void frmCurrencies_Load (object sender, EventArgs e)
{
datCurrencies = frmMain.DATA.Currencies;
DisplayData();
}
private void btnReplace_Click (object sender, EventArgs e)
{
intIndex = lstCurrencies.SelectedIndex;
Currency c = datCurrencies[intIndex];
if (txtEntry.Text.Trim().Length > 0)
{
SetValues();
c.Name = strEntry;
c.HandlesGSC = blnGSC;
c.Amount = 0;
datCurrencies[intIndex] = c;
}
ResetFields();
DisplayData();
}
private void btnCancel_Click (object sender, EventArgs e)
{
this.Close();
}
private void btnAdd_Click (object sender, EventArgs e)
{
if (txtEntry.Text.Trim().Length > 0)
{
SetValues();
Currency c = new Currency();
c.Name = strEntry;
c.HandlesGSC = blnGSC;
c.Amount = 0;
datCurrencies.Add(c);
}
ResetFields();
DisplayData();
}
private void btnRemove_Click (object sender, EventArgs e)
{
intIndex = lstCurrencies.SelectedIndex;
if (intIndex >= 0)
datCurrencies.RemoveAt(intIndex);
ResetFields();
DisplayData();
}
private void btnApply_Click (object sender, EventArgs e)
{
frmMain.DATA.Currencies = datCurrencies;
}
private void btnAccept_Click (object sender, EventArgs e)
{
frmMain.DATA.Currencies = datCurrencies;
this.Close();
}
private void lstCurrencies_SelectedIndexChanged (object sender, EventArgs e)
{
intIndex = lstCurrencies.SelectedIndex;
Currency c = datCurrencies[intIndex];
txtEntry.Text = c.Name;
chkGSC.Checked = c.HandlesGSC;
}
#endregion
#region Methods
private void DisplayData ()
{
lstCurrencies.Items.Clear();
for (int i = 0; i < datCurrencies.Count; i++)
{
string gsc = "";
if (datCurrencies[i].HandlesGSC)
gsc = "*";
else
gsc = " ";
lstCurrencies.Items.Add("[ " + gsc + " ] " + datCurrencies[i].Name);
}
}
private void ResetFields ()
{
strEntry = "";
blnGSC = false;
txtEntry.Text = strEntry;
chkGSC.Checked = blnGSC;
txtEntry.Focus();
}
private void SetValues ()
{
string entry = ToAllUpper(txtEntry.Text);
strEntry = entry;
blnGSC = chkGSC.Checked;
}
private string ToAllUpper (string str)
{
string entry = "";
for (int i = 0; i < str.Length; i++)
{
string c = "";
if (i == 0)
c = str.Substring(0, 1).ToUpper();
else if (str.Substring(i, 1) == " ")
{
c = " ";
blnUpperFlag = true;
}
else if (blnUpperFlag)
{
c = str.Substring(i, 1).ToUpper();
blnUpperFlag = false;
}
else
c = str.Substring(i, 1);
entry += c;
}
return entry;
}
#endregion
}
}
Any help you can toss me and help me understand what might be happening would be great (or you see a bug or mistake I don't).
Thanks!
This line of code datCurrencies = frmMain.DATA.Currencies is actually creates another one reference to frmMain.DATA.Currencies and doesn't deep copying it.
So all changes you made - is actually made on original object.
You have to clone it (create deep copy), not just create additional reference.
For example, if your Currency is struct (value-type), following will be sufficient:
datCurrencies = new List<Currency>(frmMain.DATA.Currencies);
But if your Currency is class - you may consider following approach:
create Clone method in your Currency class that will return clone of current object and then populate your datCurrencies like:
datCurrencies = new List<Currency>(frmMain.DATA.Currencies.Count);
foreach(var currency in frmMain.DATA.Currencies)
datCurrencies.Add(currency.Clone());
You copy the reference to a list here:
datCurrencies = frmMain.DATA.Currencies;
Afetr this asignment there is still just one list and datCurrencies points to this one global list.
Instead you need to create a deep copy i.e copy the contents from your global list to your local list.

ASP.NET C# change selected value from drop down list output to label

Ok so the problem i am having is with a drop down list.
the drop down list is supposed to output (Drinklabel) the selected value, it dose this but only the first in the list (the drop down list is generated by session variable).
I would like it so i could use the drop down list, select new value then have the label (Drinklabel) update itself.
*code bellow *
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
Drinklabel.Text = "Your Chosen Beverage is A " + DropDownList1.SelectedValue.ToString() + " Drink.";
}
////////////////////////////////////////////////////////////
Full about page code
public partial class About : Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyFruit = Session["Fruitname"] as List<string>;
//Create new, if null
if (MyFruit == null)
MyFruit = new List<string>();
DropDownList1.DataSource = MyFruit;
DropDownList1.DataBind();
}
public List<string> MyFruit { get; set; }
protected void ButtonCalculate_Click(object sender, EventArgs e)
{
decimal total = calculatePrice(DropDownList1.SelectedItem.Text,
TextBoxQuantity.Text.Trim());
LabelResult.Text = "You would like " + TextBoxQuantity.Text.Trim() +
DropDownList1.SelectedItem.Text + "(s) for a total of $" +
total.ToString();
}
private decimal calculatePrice(string p1, string p2)
{
throw new NotImplementedException();
}
private decimal calculatePrice(string fruitName, int quantity)
{
// Ask the database for the price of this particular piece of fruit by name
decimal costEach = GoToDatabaseAndGetPriceOfFruitByName(fruitName);
return costEach * quantity;
}
private decimal GoToDatabaseAndGetPriceOfFruitByName(string fruitName)
{
throw new NotImplementedException();
}
}
you are not checking the session object before assigning it to the Local List MyFruit.
hence add a check before assigning the Session object
Replace this:
MyFruit = Session["Fruitname"] as List<string>;
With following:
if(Session["Fruitname"]!=null)
MyFruit = Session["Fruitname"] as List<string>;
and in your Question you said that you are able to get only one item from DropDownList always.
but here you are only assigning Session object one time so obviously you will get one item.

Categories

Resources