i have an asp.net webform where the user can enter data and submit into a database table on sql-server-2008
the user picks the primary key of the record he wants to edit by going to the URL http://someurl/default.aspx?primarykey=123
based on the primary key the webform is succesfully filled out
the user can make changes to any data and resubmit it to be updated in the database for that specific PK
here is how i grab data from the userform:
public LOMDLL.Main_Lom_Form PopulateMainForm()
{
//populate class
LOMDLL.Main_Lom_Form TheForm = new LOMDLL.Main_Lom_Form();
try
{
TheForm.received_date = received_dateTextbox.Text.ToDateTime();
TheForm.site_of_occurrence = site_of_occurrenceTextBox.Text.ToUpper();
TheForm.occurrence_date = occurrence_dateTextBox.Text.ToDateTime();
TheForm.report_by = report_byTextBox.Text;
if (RadioButtonList1.SelectedValue != "Other:")
TheForm.identified_by = RadioButtonList1.SelectedValue;
else
TheForm.identified_by = "Other: " + otherTextBox.Text;
TheForm.practice_code = txtPracticeCode.Text.ToUpper();
TheForm.comments = txtComments.Text;
TheForm.report_date = report_dateTextBox.Text.ToDateTime();
//TheForm.windows_user = WindowsIdentity.GetCurrent().Name;
TheForm.windows_user = HttpContext.Current.User.Identity.Name.ToString();
TheForm.computer_name = System.Environment.MachineName;
TheForm.time_stamp = DateTime.Now;
}
catch (Exception e)
{
}
return TheForm;
}
it is returning OLD data. it returns what was in the fields BEFORE the user updated the data in the textboxes.
another words when i debug, and i look at the values that are being stored in the textboxes they DO NOT reflect the changes made by the user. the values are the same as they are currently in the database before the update!
what am i doing wrong?
is there some kind of disconnect between client and server?
I would check your bindings when you load the page. Chances are you are re-binding your page from your database before you try to read the changed values.
Check your Page_Load and make sure you are only binding your page with database information when !Page.IsPostBack and not every time you load your page.
Related
I'm completely new to C# programming and I'm trying to learn on my own. Currently I'm building a mini-project to exercise.
I understand that the user layer should not have any data query for security reasons perhaps?
So I have created a separate Data Access class to retrieve data. This is what my data access class looks like(I'll be using stored procedures for better security once I learn how to use it):
public class DataAccess
{
public List<Customer> FilteredCustomersList(string name)
{
using (IDbConnection connection = new MySql.Data.MySqlClient.MySqlConnection(Helper.CnnVal("FineCreteDB")))
{
var output = connection.Query<Customer>($"SELECT * from `Customers` WHERE `Cust_Name` LIKE '{name}'").ToList();
return output;
}
}
Basically I send over a string from the user form to query the database, the data is retrieved and stored in a list. User form:
private void RetrieveData()
{
try
{
DataAccess db = new DataAccess();
filteredcustomers = db.FilteredCustomersList(CustomerNameTxtBox_AutoComplete.Text);
ntn_num = filteredcustomers.Select(x => x.Cust_NTN).ElementAt(0);
strn_num = filteredcustomers.Select(x => x.Cust_STRN).ElementAt(0);
address = filteredcustomers.Select(x => x.Cust_Address).ElementAt(0);
phone_num = filteredcustomers.Select(x => x.Cust_Phone).ElementAt(0);
id_num = filteredcustomers.Select(x => x.Cust_ID).ElementAt(0);
}
catch (Exception)
{
MessageBox.Show("Customer not found. If customer was recently added, try updating DB.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
DataAccess db = new DataAccess();
filteredcustomers = db.AllCustomersList();
ntn_num = "";
strn_num = "";
address = "";
phone_num = "";
}
}
On the user form side, "filteredcustomers" holds the list of data sent back, now here is the problem: I use the filteredcustomers list to extract the different column values like so:
address = filteredcustomers.Select(x => x.Cust_Address).ElementAt(0);
and then use them to populate the respective textboxes like:
Address_TxtBox.Text = address;
Everything works fine, but I don't want the userform to have these queries for all individual columns, because from what I've understood so far, this is bad programming and bad for security as well.
Can anyone guide me how I can keep the values in Data Access layer and just call them into my form?
I'm sorry if this is a long post, I'm just learning and wanted to be as detailed as possible.
You're already doing everything reasonably correctly as per how Dapper is to be used. Dapper doesn't maintain a local graph of entities from the db, track changes to it and automatically save them. If you want that, use something like EF
For dapper you retrieve data with a SELECT and send it back with an UPDATE
If you're only expecting one Customer for the name, do this:
var output = connection.QueryFirstOrDefault<Customer>($"SELECT * from `Customers` WHERE `Cust_Name` LIKE #n", new { n = name });
https://dapper-tutorial.net/queryfirst
This will return just one customer instance (or null; check it!) meaning you can tidy up your form code to:
c = db.FilteredCustomer(CustomerNameTxtBox_AutoComplete.Text);
ntn_num = c?.Cust_NTN;
strn_num = c?.Cust_STRN;
And so on
Your "if customer was recently added try updating db" doesn't really make sense- the query is done live, so the db is about as up to date as it can be
I am trying to figure out a way for my program not to update the sql database if some fields are blank when I hit the submit form. Right now when I submit it to the sql database, if the fields are blank, it updates it as blank. Is there a way for my code not to behave like this?
Thanks
//field names in the table
string update = #"UPDATE Master_List
SET Date_Complete1 = #Date_Complete1, Pass_Fail = #Pass_Fail, CRC_Number = #CRC_Number, QN_Number = #QN_Number, Notes = #Notes WHERE Job_Number = #Job_Number"; //parameter names
using (SqlConnection conn = new SqlConnection(connString)) //using allows disposing of low level resources
{
try
{
conn.Open();//open new connection
command = new SqlCommand(update, conn); // create the new sql command object
// Read value from form and save to the table
command.Parameters.AddWithValue(#"Job_Number", jobTxt.Text);
command.Parameters.AddWithValue(#"Pass_Fail", comboBox1.Text);
command.Parameters.AddWithValue(#"Date_Complete1", opBox1.Text);
command.Parameters.AddWithValue(#"CRC_Number", crcTxt.Text);
command.Parameters.AddWithValue(#"QN_Number", qnTxt.Text);
command.Parameters.AddWithValue(#"Notes", notesTxt.Text);
command.ExecuteNonQuery(); // Push form into the table
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // If there is something wrong, show the user message
}
}
Assuming that you want to update some of the fields if one or more fields are blank, then you can do this:
UPDATE Master_List
SET Date_Complete1 = ISNULL(NULLIF(#Date_Complete1,''),Date_Complete1),
Pass_Fail = ISNULL(NULLIF(#Pass_Fail,''),Pass_Fail),
CRC_Number = ISNULL(NULLIF(#CRC_Number,''),CRC_Number),
QN_Number = ISNULL(NULLIF(#QN_Number,''),QN_Number),
Notes = ISNULL(NULLIF(#Notes,''),Notes)
WHERE Job_Number = #Job_Number
If you don't want any fields to update if any fields are blank, then just check them in an if statement.
Perform checks on your input data before your sql code is executed.
simply return out of the function if any checks you want to do fail e.g.
If(string.IsNullOrEmpty(variable to check))
... Return or configure error message for user ...
Or perform some logic to show the user you dont want blank fields.
If you are going to validate that you should change your database field properties to do that task.
if you want to do this with some code you should add something like this:
bool val = true;
if (jobTxt.Text.Trim() == string.Empty) {
val = false;
}
if(val==true){
command.ExecuteNonQuery();
}
else{
MessageBox.Show("Some field is empty")
}
and repite the sentence if for each textbox you want to do a validation.
i hope this help you.
You can say which textbox is empty on the else sentences on the textbox.
I have define the employee userID at the login page in order to save the development time. At the login page there is a button called 'Reset Password'. The process is that when I click on the reset button, the password inside the database will become NULL for that userID. I have manage to call the userID, but do not know how to set the password to become NULL.
Below is my code for the process flow.
Employee emp = null;
string src = "07070";
if (TransState.GetType() == typeof(EnterUserId) || TransState.GetType() == typeof(EnterPassword))
{
if (Auth.GetEmpoyeeClassByBarcode(src, out emp) == 1)
{
// set the ui button fo successful user login
int x = LoginCheckBarcode(src, out emp);
// loadTask(auth);
// Direct to login menu
Param.Operation = Constant.LOGIN;
ChangeState(typeof(TaskSelected));
return 1;
}
else
{
return 0;
}
}
You need to have some extra validation other than just deleting the password otherwise anyone could just reset and delete the password and proceed to log in.
That being said, to change the password you would need to query your database which I assume is sql server since you list Winforms.
UPDATE table
SET password = value
WHERE userID = value
;
I am developing an application in which their exist a problem. When i click on to submit button, the data is inserted into db. But when i press ctrl+R or f5 a chrome or IE pop up occurs which says Confirm Form Resubmission. when i click continue then the record is duplicated into database.
My question is,
Why is this popup occuring? because of the postback? if because of postback then do my code have any issues or it occurs with every body when doing postback.
Will using mvc will solve this issue completely?
My code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
paramArray = new string[9];
paramValues = new object[9];
try
{
paramArray[0] = "#AccountNumber";
paramValues[0] = (!string.IsNullOrEmpty(this.txtAccountNumber.Value) ? this.txtAccountNumber.Value.Trim() : string.Empty);
paramArray[1] = "#OpeningBalance";
paramValues[1] = (!string.IsNullOrEmpty(this.txtOpeningBalance.Value) ? Convert.ToDouble(this.txtOpeningBalance.Value.Trim()) : 0.00);
paramArray[2] = "#ClosingBalance";
paramValues[2] = (!string.IsNullOrEmpty(this.txtClosingBalance.Value) ? Convert.ToDouble(this.txtClosingBalance.Value.Trim()) : 0.00);
paramArray[3] = "#PaymentMode";
paramValues[3] = this.ddlModeofPayment.Value;
paramArray[4] = "#PaymentDate";
paramValues[4] = this.dtPaymentDate.Value;
paramArray[5] = "#PaymentAmount";
paramValues[5] = (!string.IsNullOrEmpty(this.txtPaymentAmount.Value) ? Convert.ToDouble(this.txtPaymentAmount.Value.Trim()) : 0.00);
paramArray[6] = "#isAccount";
paramValues[6] = true;
paramArray[7] = "#UserId";
paramValues[7] = (!string.IsNullOrEmpty(this.User.Identity.Name.Remove(0, 7)) ? this.User.Identity.Name.Remove(0, 7) : string.Empty);
paramArray[8] = "#isProcessed";
paramValues[8] = default(bool);
var success = herlperUtility.ExecuteParameterizedQuery("{CALL asp_sp_InsertPayment(?,?,?,?,?,?,?,?,?)}", paramArray, paramValues);
if (!string.IsNullOrEmpty(success.Rows[0]["ReferenceNumber"].ToString()))
{
this.Page.Response.Redirect("AccountPaymentScreen.aspx?flag=1");
divSuccess.Attributes.Add("style", "display:block");
this.refId.InnerText = "<b>Success!</b> The " + success.Rows[0]["ReferenceNumber"] + " has been successfuly forwarded to the supervisor";
this.ClearFields();
}
else
{
this.divFailure.Attributes.Add("style", "display:block");
}
}
catch (Exception ex)
{
this.divFailure.Attributes.Add("style", "display:block");
this.divFailure.InnerText = ex.Message;
}
}
The solution to this is to follow the Post-Redirect-Get pattern. This means that after an HTTP POST in which you do some kind of transactional activity you redirect the client to an HTTP GET.
In a very simplistic way of thinking: GET should not modify anything, while POST is there to make changes.
For example, consider the following workflow.
The user presses submit on an shopping cart page (HTTP POST).
You validate that a credit card is valid and if so charge the
account and set your warehouse activities in motion
You show a screen confirming the order.
If everything goes well and you haven't redirected the client (e.g., you show a panel with a success message and hide the cart) and the client presses refresh, the order will be resubmitted which is probably not ideal for anyone other than accounts receivable.
Following the PRG pattern, after submitting the order you would redirect to a GET page (possibly with the order id in the query string so you have some way of referencing the order) and show your success message. This page can be refreshed as many times as the customer wants (with the added bonus of being bookmarkable) with no side-effects to your back end system or the customer's wallet.
It's worth noting that you don't have to be fanatical about this. In this example if the credit card validation failed you could choose to just display the results of the POST action and toggle an error message on your page. If the user refreshes the page, the validation will run and fail again but no changes will be made to your back end system.
As for MVC - It's not so much that it's easier to accomplish this (it is), it's that you end up thinking about these kinds of things a little more than when using WebForms which (for better or worse) hides these concepts behind an abstraction.
I'm having a weird issue with my textboxes on my website.
Currently I'm making a page to allow the customer to update their credentials.
So I have a page that shows that information in textboxes (fetched from the DB in the Page_Load)
if (!Page.IsPostBack)
{
//Ingelogd
kService = new KlantService();
ingelogdeKlant = kService.GetAllByUsername(inlogsessie.GetUsername());
//Gegevens tonen
begroeting.InnerText = "Welkom " + ingelogdeKlant.voornaam + " " + ingelogdeKlant.achternaam;
txtVoornaam.Text = ingelogdeKlant.voornaam;
txtAchternaam.Text = ingelogdeKlant.achternaam;
txtStraat.Text = ingelogdeKlant.straat;
txtNummer.Text = Convert.ToString(ingelogdeKlant.nummer);
txtPostcode.Text = ingelogdeKlant.postcode;
txtStad.Text = ingelogdeKlant.stad;
}
And this is the code I use to get the text from the textboxes and send them to my DB (Trigger = Button click)
ingelogdeKlant.voornaam = txtVoornaam.Text;
ingelogdeKlant.achternaam = txtAchternaam.Text;
ingelogdeKlant.straat = txtStraat.Text;
ingelogdeKlant.nummer = Convert.ToInt16(txtNummer.Text);
ingelogdeKlant.postcode = txtPostcode.Text;
ingelogdeKlant.stad = txtStad.Text;
kService = new KlantService();
kService.UpdateKlant(ingelogdeKlant)
Tried solution #1:
Remove the IsPostBack check
Result: txtSomething.text returns the original values (not the edited ones)
Tried solution #2:
Adding the IsPostBack check
Result: txtSomething.text returns a nullpointer
I don't know what the issue could be, so any help would be appreciated.
Move the following
//Ingelogd
kService = new KlantService();
ingelogdeKlant = kService.GetAllByUsername(inlogsessie.GetUsername());
Above the if (!Page.IsPostBack)
Your ingelogdeKlant is only instantiated on the first Page_Load and not on subsequent postbacks.
Your Page class is instantiated each time a request (PostBack or not) is made, any members need to be initialised each time they are needed; they won't persist because the Page object doesn't persist.