Ticket Booking System: Database access issue - c#

I'm creating a Bus Ticket booking system. I have created a database called traveller and two tables named Useriden and BusDB respectively. In the aspx.cs file(Sign Up page), I'm checking for duplicate usernames but it simply navigates to the next page
I've tried everything but I'm unable to resolve this issue. I'm not getting any errors or warnings.
protected void BtnConfirmSignup_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=(localdb)\\MSSQLlocalDB;Initial Catalog=traveller;Integrated Security=True;Pooling=False");
SqlCommand cmd;
SqlDataReader read;
/*DEBUG: Prevent duplicate usernames*/
try
{
Session["user"] = TxtUsrName.Text;
Session["pass"] = TxtPsswd.Text;
Session["email"] = TxtEmail.Text;
cmd = new SqlCommand("select Name from Useriden",con);
con.Open();
read = cmd.ExecuteReader();
while (read.Read()) {
if ((read["Name"].ToString()).Equals(TxtUsrName.Text))
{
throw new Exception("Invalid Username");
}
else
{
Response.Redirect("SignUpNext.aspx");
}
}
}
catch (Exception ex) {
LabelUserName.Visible = true;
LabelUserName.Text = ex.Message;
con.Close();
ViewState["Caption"]=ex.Message;
}
}
On clicking the confirm button, it should check for duplicate usernames. I already have one record with the name "Faf" in my table Useriden. When I try to sign up using the same username, it's not throwing an exception instead it navigates to SignUp.aspx.
The duplicate check is only valid if there's one record. I'll modify the logic so that it works for more than record but right now, it's not even working for a single record.

Related

Not able to perform insert query operation

I am working on my simple task in c# with service based database. I have a service-based database where I have table staff with columns id, name and password. I am trying to insert new record into that table, with C# code, but it's not inserting, just telling me "No Record ADDED" even there is no error.
My code is:
private void button5_Click(object sender, EventArgs e)
{
try
{
connetionString = Properties.Settings.Default.testdbConnectionString;
cnn = new SqlConnection(connetionString);
cnn.Open();
SqlCommand command6;
string sql6 = null;
sql6 = "insert into staff (name,pwd,id) values(#n,#p,#fid)";
command6 = new SqlCommand(sql6, cnn);
command6.Parameters.AddWithValue("#n", "jhon");
command6.Parameters.AddWithValue("#p", "test");
command6.Parameters.AddWithValue("#fid", 1);
int result = command6.ExecuteNonQuery();
if (result == 0)
{
MessageBox.Show("Record ADDED");
}
else
{
MessageBox.Show("No Record ADDED");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
If you need more detail you my ask but please correct my mistake. Thanks
The result of ExecuteNonQuery is the number of records affected. Your if statement is the wrong way round... if the result doesn't equal zero then something was inserted.

Catching Button Tampering By a User C#

Login Error
As you can see, I want to catch the exception if the user is tampering the Login Button if there are no values in the fields or if it doesn't match info in the database.
For example:
The field has no values and I click Login button once, it says the error. After I clicked OK button, I click Login button again and now it says,
"ExecuteReader requires an open and available Connection. The connection's current state is closed."
I use 3 tier Architecture Windows Application.
BEL:
public SqlDataReader Login(BELLogin bellog)
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = Con.getcon();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT username,password FROM tbl_login WHERE username = #Username AND password = #Password";
cmd.Parameters.AddWithValue("#Username", bellog.Acctname);
cmd.Parameters.AddWithValue("#Password", bellog.Password);
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
BAL:
public class BELLogin
{
public string Acctname { get; set; }
public string Password { get; set; }
}
DBConnection:
public SqlConnection getcon()
{
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
else if (con.State == System.Data.ConnectionState.Open)
con.Close();
return con;
}
public DataTable ExeReader(SqlCommand cmd)
{
getcon();
cmd.Connection = getcon();
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
return dt;
}
GUI:
private void btn_login_Click(object sender, EventArgs e)
{
BELog.Acctname = txb_accName.Text;
BELog.Password = txb_password.Text;
SqlDataReader dr;
dr = BALog.Login(BELog);
if (txb_accName.Text == "" || txb_password.Text == "")
{
MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
if (dr.HasRows == true)
{
dr.Read();
Inventory Inv = new Inventory();
Inv.Show();
this.Hide();
}
else
{
MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
dr.Close();
}
Logging in is ok but what if the user tampering the button?
Thank you for helping me :D
You need to change your code in gui like this:
//Put code to get the reader inside else clause and close the reader in the same else clause. Also ideally you should return if you encounter. I have added it and commented it.
//Off course you would need to put more effort to make this code better. You will get to that as you get more experience. For now this should make your app work.
private void btn_login_Click(object sender, EventArgs e)
{
BELog.Acctname = txb_accName.Text;
BELog.Password = txb_password.Text;
if (txb_accName.Text == "" || txb_password.Text == "")
{
MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
//return;
}
else
{
SqlDataReader dr;
dr = BALog.Login(BELog);
if (dr.HasRows == true)
{
dr.Read();
Inventory Inv = new Inventory();
Inv.Show();
this.Hide();
}
else
{
MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
dr.Close();
}
}
Do not reuse connections like this, it is bad practice and unnecessary.
Wrap all type instances that implement IDisposable in using blocks so the resources are released. In your case SqlConnection, SqlCommand, SqlDataReader, DataTable.
From a security standpoint you should never store your user passwords (anywhere, not DB, not files, not registry, etc. just do not store them). You need to store the hash, not the password, and compare hashes
Adhere to loose the coupling / high cohesion principle. Essentially expose as little as possible (especially implementation details) from your methods / classes so they can be easily reused and changed. Currently you are passing around and sharing DB objects, this will make your code brittle and very difficult to track down where problems are. Here is your code with a little bit of refactoring, notice that if you have another issue with a connection during login it would now be very easy to figure out where that might be.
// place in new code file
public class UserManager{
public BELLogin FindLogin(string userName, string password){
if(string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
return null;
using(var connection = new SqlConnection("connectionStringPointerFromAppConfigHere"))
using(SqlCommand cmd = new SqlCommand("SELECT username,password FROM tbl_login WHERE username = #Username AND password = #Password", connection))
{
connection.Open();
cmd.Parameters.AddWithValue("#Username", bellog.Acctname).SqlDbType = SqlDbType.VarChar;
// BAD practice! Use a secure hash instead and store that not the password!
cmd.Parameters.AddWithValue("#Password", bellog.Password).SqlDbType = SqlDbType.VarChar;
using(SqlDataReader dr = cmd.ExecuteReader())
{
if(dr.Read())
return new BELLogin() {Acctname = dr.GetString(0), Password = dr.GetString(1)}; // passed in is same as in datareader
}
}
return null;
}
}
From your login form class
private void btn_login_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txb_accName.Text) || string.IsNullOrEmpty(txb_password.Text))
{
MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
var manager = new UserManager();
var user = manager.FindLogin(txb_accName.Text, txb_password.Text);
if (user != null)
{
Inventory Inv = new Inventory();
Inv.Show();
this.Hide();
}
else
{
MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
Your btn_login_Click method appears to call BALog.Login(BELog) prior to checking if there are any valid values in the username and password textboxes. Simply move the validation to the top of btn_login_Click method, and return if the fields are empty:
if (txb_accName.Text == "" || txb_password.Text == "")
{
MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
The code in the else portion of that if statement can stay where it is, just not inside an else. The method will exit due to return statement if there are no valid values in the username and password textboxes.
As others have suggested, you should review your code to ensure you really want this structure; but if you do want to keep it that way, this simple fix will solve your problem.
Just get rid of your DBConnection object, it's not really doing anything and just making your structure complex:
public BELLogin Login(BELLogin bellog)
{
SqlConnection conn = new SqlConnection(connectionsString);
try
{
using (SqlCommand cmd = new SqlCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT username,password FROM tbl_login WHERE username = #Username AND password = #Password";
cmd.Parameters.AddWithValue("#Username", bellog.Acctname);
cmd.Parameters.AddWithValue("#Password", bellog.Password);
//really this should be in a using as well.
//You be better off reading your data
//into a class and returnig the class not the reader.
using (SqlDataReader dr = cmd.ExecuteReader())
{
BELLogin obj = new BELLogin();
while(dr.Read())
{
//populate obj
}
return obj;
}
}
}
finally
{
conn.Close();
conn.Dispose();
}
}
also the way you use it can cause memory leaks as your not explicitly disposing and closing your connections. Always dispose Sql objects in C#. Be wary of exceptions too. Any exceptions in your code will not close the connection, etc. This will result in memory leaks and connections locking

How to Save the data in Page using C#

I am working one portal where user can login and will enter his details and later he can view those details after login again. But unfortunately data is not not displaying in page. Here is I am giving everything which I did.
Code Explanation:
This is the Button code for data in database.
protected void btnContactInfoSave_click(object sender, EventArgs e)
{
if (chkContactUpdate.Checked)
{
string[] ContactInfoData = new string[6];
ContactInfoData[0] = GlobalVars.UserEmail;
ContactInfoData[1] = txtCnct.Text;
ContactInfoData[2] = txtAltCnct.Text;
ContactInfoData[3] = txtEmrCnct.Text;
ContactInfoData[4] = txtPrsnEmail.Text;
ContactInfoData[5] = txtOfsEmail.Text;
Utilities.sqlUploadContactInfoData(ContactInfoData);
}
else
{
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Error", "alert('Please click on the checkbox before Saving.');", true);
}
}
Here is the code for the Button creation :
When user clicks this button data should be added in database. wat ever the data user enters it has to save in database.
Code for uploading the data in database.
public static void sqlUploadContactInfoData(string[] Userdata) // code for saving the data in database
{
using (SqlConnection sqlConn = PortalDBConnection())
{
try
{
sqlConn.Open();
string spName = "sp_testSample";
SqlCommand cmd = new SqlCommand(spName, sqlConn);
cmd.Parameters.AddWithValue("#CnctNum", Userdata[1].ToString());
cmd.Parameters.AddWithValue("#AltCnctNum", Userdata[2].ToString());
cmd.Parameters.AddWithValue("#EmerCnctNum", Userdata[3].ToString());
cmd.Parameters.AddWithValue("#PrsnEmail", Userdata[4].ToString());
cmd.Parameters.AddWithValue("#OfsEmail", Userdata[5].ToString());
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConn;
cmd.ExecuteNonQuery();
}
catch (SqlException)
{
ErrorMsg("Server Error", "Server Error ! Please try again Later.");
}
}
}
Here I have a problem that I am unable to display the data in page.
When user clicks the button, data is saving in database. The problem is when user login and fill the data and he can save the data. once he logged out from portal and after login again data is not displaying there. Data need to save in page also.
Any problem in above code..??
string strCnctNum = txtCnctNum.Text;
//Then reset your control like below
`txtCnctNum.Text = "";
txtAltCnctNum.Text = "";
...
etc
// Then Use This Code to To Retrieve & Display Data
using (SqlConnection oSqlConnection = new SqlConnection("YourConnectionString"))
{
string strCommand = "Select * from YourTableName where CnctNum="+ strCnctNum +";
SqlCommand oCmd = new SqlCommand(strCommand, oSqlConnection);
oSqlConnection.Open();
using (SqlDataReader oReader = oCmd.ExecuteReader())
{
while (oReader.Read())
{
txtCnctNum.Text = oReader["CnctNum"].ToString();
txtAltCnctNum.Text = oReader["AltCnct"].ToString();
.....
etc
}
oSqlConnection.Close();
}
}`

Insert INTO error when transferring data from DataTable to Access Database

I have a datatable with 5 columns, (Song, Artist, Album, Genre, Time) the table allows for me to enter as many rows as i want to create a playlist of music, when the user sees fit they can click the button export the data to access. My access database has a table named "Playlist" with the same 5 columns as the data table. When trying to transfer the data, i keep getting the exception error for the Insert INTO statement and I have no idea why because i am using a commandBuilder. I have attached my class and method thats performing this action.
Please advise!
public void ExportPlaylistToAccess(DataTable playlist)
{
// open connection to the database pathed to
String connection = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data source= D:\CIS 465\Final Project\VirtualiPod\iTunesPlaylistDatabase.accdb";
using (OleDbConnection con = new OleDbConnection(connection))
{
var adapter = new OleDbDataAdapter();
adapter.SelectCommand = new OleDbCommand("SELECT * from [Playlist]", con);
var cbr = new OleDbCommandBuilder(adapter);
cbr.GetDeleteCommand();
cbr.GetInsertCommand();
cbr.GetUpdateCommand();
try
{
con.Open();
adapter.Update(playlist);
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message, "Database Error");
}
catch (Exception x)
{
MessageBox.Show(x.Message, "Exception Error");
}
}
dataTable creation
private void createPlaylist_Click(object sender, EventArgs e)
{
if (playlist.Rows.Count == 0)
{
playlist.Columns.Add("Song");
playlist.Columns.Add("Artist");
playlist.Columns.Add("Album");
playlist.Columns.Add("Genre");
playlist.Columns.Add("Time");
dataGridView1.DataSource = playlist;
}
else if (playlist.Rows.Count > 0)
{
MessageBox.Show("Please clear your current playlist to create a new one.");
}
}
// adds song to playlist for user upon click
private void addToPlaylist_Click(object sender, EventArgs e)
{
IITTrackCollection tracks = app.LibraryPlaylist.Tracks;
IITTrack currentTrack = app.CurrentTrack;
DataRow newRow;
newRow = playlist.NewRow();
newRow["Song"] = currentTrack.Name;
newRow["Artist"] = currentTrack.Artist;
newRow["Album"] = currentTrack.Album;
newRow["Genre"] = currentTrack.Genre;
newRow["Time"] = currentTrack.Time;
playlist.Rows.Add(newRow);
dataGridView1.DataSource = playlist;
}
Time is a reserved word. For some reason the command builder does not surround fields that are database reserved words (time, date, long etc.) with brackets [time] which would allow the insert query to work correctly. Without the brackets the insert will fail as the SQL compiler does not know if the string time is a sql command or a field name. The only solution I've found is to rename your database fields so that they are not in conflict with the database reserved names. Hopefully MS will eventually fix this mistake.

How do I search for values in a database using a value from a seperate database?

I'm making a system for checking bookings online using a booking ID, I've done all the code and when I run my application on the web browser it appears to disconnect with the message "Problem loading page"
this is the code used for checking the system when pressing the button
protected void Button1_Click(object sender, EventArgs e)
{
int custval = 70757;
if (BookID.Text == Convert.ToString(custval))
{
try
{
SqlConnection GuestBookings = new SqlConnection("Data Source=dell-vostro;Initial Catalog=HotelConference;Persist Security Info=True;User ID=website_application_testing;Password=***********");
SqlCommand sc = new SqlCommand();
sc.Connection = GuestBookings;
GuestBookings.Open();
sc.CommandText = ("SELECT CustomerFirstName, CustomerLastName FROM tblBookingGuests WHERE BookingID="+BookID.Text+")");
sc.ExecuteNonQuery();
GuestBookings.Close();
}
catch (Exception ex)
{
}
}
}

Categories

Resources