Ticket Booking System: Comparing two strings [duplicate] - c#

This question already exists:
Ticket Booking System: Database access issue
Closed 3 years ago.
Okay so I'm basically trying to verify whether the username being entered is a duplicate but there's a problem in the string comparison inside the while loop
I tried using a temp label to verify that the values are being extracted correctly.
protected void BtnConfirmSignup_Click(object sender, EventArgs e)
{
int f = 0;
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;
//Label6.Text = "Faf";
// if ((Label6.Text).Equals(TxtUsrName.Text))
//{
// Label6.Text = "dafuqqqq";
//}
//{
// Label6.Text = "wtf";
// Label6.Text = TxtUsrName.Text;
//}
cmd = new SqlCommand("select Name from Useriden", con);
con.Open();
read = cmd.ExecuteReader();
while (read.Read())
{
Label6.Text = read["Name"].ToString();
Label1.Text = "aaa";
//Label6.Text = "Faf";
if ((Label6.Text).Equals(TxtUsrName.Text))
{
f = 1;
//Label6.Text = "Duplicate Username";
break;
}
}
if (f == 1)
{
Label6.Text = "Duplicate Username";
}
else if (f == 0)
{
Response.Redirect("SignUpNext.aspx");
}
}
catch (Exception ex)
{
LabelUserName.Visible = true;
LabelUserName.Text = ex.Message;
con.Close();
ViewState["Caption"]=ex.Message;
}
}
Expected: I'm entering a duplicate name so it should the change the text of the label to Duplicate Username but it instead navigates to the next page/The value of f never changes.

To add to what #EdPlunkett pointed out with the Ordinal Case... You should also make sure there are no extra spaces.
Label6.Trim().Text.Equals(TxtUsrName.Text.Trim(), StringComparison.OrdinalIgnoreCase)
Side note: You also don't seem to be closing your SqlConnection unless there is an exception. You should maybe use using()

Related

System.InvalidOperationException' in System.Data.dll c# making login to the file. sql

im creating e grades project on c#, and i cant normally connect to database. Writing https://i.stack.imgur.com/itJuX.png
Maybe you can help me ? Not working in login.cs. Last job then i do it it was working.
private void button1_Click(object sender, EventArgs e)
{
try
{
using (SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\dienynas.mdf;Integrated Security=True;"))
{
conn.Open();
SqlCommand cmd = new SqlCommand("select * from users", conn);
SqlDataReader sdr = cmd.ExecuteReader();
int id = 0;
bool pass = false;
while (sdr.Read())
{
if (sdr[0].ToString() == textBox1.Text && sdr[0].ToString() == textBox2.Text)
{
pass = true;
id = (int)sdr[0];
break;
}
}
if (pass == false)
{
MessageBox.Show("Password for this user is incorrect");
id = (int)sdr[0];
pass = true;
}
else
{
Form1 frm = new Form1(id);
Hide();
frm.Show();
}
conn.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Your problem is in your if statement after the loop.
if (pass == false)
{
MessageBox.Show("Password for this user is incorrect");
id = (int)sdr[0];
pass = true;
}
In that if block you are accessing your SqlDataReader, which very possibly has exited the while loop after returning false upon reading indicating that there is no more data to be read. If there is no data, then you will get an error when attempting to read data that is not there.
I would think that one of the reasons you are exiting the while without ever having a match is that, unless both TextBox1 and TextBox2 contain a matching string you will never have a match. The following line is comparing those text box values to the exact same data value. Unless the text is identical between those text boxes then this statement will always be false.
if (sdr[0].ToString() == textBox1.Text && sdr[0].ToString() == textBox2.Text)
I am guessing that you intended something like this:
if (sdr[0].ToString() == textBox1.Text && sdr[1].ToString() == textBox2.Text)
Edit
With all of that being said, there is a lot of room for refactoring in this code. For one thing, generally performing database operations in a button handler can lead to unresponsive dialog windows and is something to be avoided. You are also using some other objects which are disposable and so you should be cleaning those up as well. I will rewrite the function a little to show you some of the cleanup, but I don't have time to go through splitting it into threads and it is outside the scope of your question.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection conn = null;
SqlCommand cmd = null;
SqlDataReader sdr = null;
try
{
var textBox1 = textBox1.Text;
var textBox2 = textBox2.Text;
conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\dienynas.mdf;Integrated Security=True;");
conn.Open();
cmd = new SqlCommand("select * from users", conn);
sdr = cmd.ExecuteReader();
int id = -1;
while (sdr.Read())
{
var text0 = sdr[0].ToString();
var text1 = sdr[1].ToString();
// NOTE: You could add the string comparison type here as well
if (text0.Equals(textBox1) && text1.Equals(textBox2))
{
id = (int)sdr[0];
break;
}
}
if (id == -1)
{
MessageBox.Show("Password for this user is incorrect");
}
else
{
Form1 frm = new Form1(id);
Hide();
frm.Show();
}
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
sdr?.Dispose();
cmd?.Dispose();
conn?.Dispose();
}
}

C# - Cannot get value from database

In my application I have a login system. It's basic so I don't need any encryption. The problem is that when I want to login, I insert the credentials (username and password) but it doesn't make anything. My code is:
public void iniciarsessaobutton_Click(object sender, EventArgs e)
{
string txtuser = textusername.Text;
string txtpass = textlogin.Text;
MySqlCommand cmd = new MySqlCommand("SELECT password FROM empregados WHERE user='" + txtuser + "';", mConn);
mConn.Open();
MySqlDataReader login = cmd.ExecuteReader();
login.Read();
string getpass = login["password"].ToString();
if (getpass == txtpass)
{
mConn.Close();
MessageBox.Show("Sessão iniciada");
Admin adm = new Admin();
this.Hide();
adm.Show();
}
else
{
mConn.Close();
MessageBox.Show("Não foi possivel iniciar sessão. Insira a password corretamente.");
}
}
I'd like to propose some fixes mentioned in the comments along with some general improvements. See my comments in the code for the issues addressed:
public void iniciarsessaobutton_Click(object sender, EventArgs e)
{
string txtuser = textusername.Text;
string txtpass = textlogin.Text;
// Put your connection into a using() block
using (MySqlConnection conn = new MySqlConnection(variableWithYourConnectionStringHere))
{
// Put your commend into a using() block
// enclose your column names in backticks to avoid conflict with MySql reserved keywords
// add a placeholder (#username) for your parameter
// use LIMIT 1 if you only expect 1 row matching your condition
using(MySqlCommand cmd = new MySqlCommand("SELECT `password` FROM empregados WHERE `user` = #username LIMIT 1", conn))
{
mConn.Open();
// add a parameter with your TextBox value
cmd.Parameters.AddWithValue("#username", txtuser);
// If you only retrieve 1 value, use ExecuteScalar to return only 1 value
// cast the returned object as string
string getpass = cmd.ExecuteScalar() as string;
if (getpass == txtpass)
{
MessageBox.Show("Sessão iniciada");
Admin adm = new Admin();
this.Hide();
adm.Show();
}
else
{
MessageBox.Show("Não foi possivel iniciar sessão. Insira a password corretamente.");
}
}
}
}

IndexOutOfRangeException at the time of Login in Asp.net C#

In my Asp.Net application at the time of Login, I am first authenticating the User then getting some important information in session variables and it's working fine too.
However after sometime when session expires and I have to login again then it shows IndexOutOfRangeException in GetDetail() method. Here is my Login Button Code:
protected void btnLogin_Click(object sender, EventArgs e)
{
Session["UserName"] = txtUserName.Text;
string DefaultYear = GetDefaultFinYear();
if (DefaultYear != string.Empty)
{
DefaultYear = "connect" + DefaultYear;
Connections.Init(DefaultYear);
SqlDataAdapter adp = new SqlDataAdapter();
try
{
adp = new SqlDataAdapter("CheckLogin_sp", Connections.Connection[Session["UserName"].ToString()]);
adp.SelectCommand.Parameters.AddWithValue("#UserName", txtUserName.Text.Trim());
adp.SelectCommand.Parameters.AddWithValue("#Pwd", txtPassword.Text.Trim());
adp.SelectCommand.Parameters.AddWithValue("option", "Authenticate".Trim());
adp.SelectCommand.CommandType = CommandType.StoredProcedure;
if (Connections.Connection[Session["UserName"].ToString()].State == ConnectionState.Closed)
{
Connections.Connection[Session["UserName"].ToString()].Open();
}
SqlDataReader dr = adp.SelectCommand.ExecuteReader();
if (dr.HasRows)
{
Session["value"] = "admin";
dr.Close();
dr.Dispose();
GetDetails();
Response.Redirect("~/Masters/home.aspx", false);
}
else
{
MessageBox.Show("Invalid Password");
txtUserName.Text = string.Empty;
}
Connections.Connection[Session["UserName"].ToString()].Close();
adp.Dispose();
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
finally
{
Connections.Connection[Session["UserName"].ToString()].Close();
adp.Dispose();
}
}
else
{
MessageBox.Show("Invalid UserName");
}
}
GetDetails() Method:
private void GetDetails()
{
SqlCommand cmd = new SqlCommand();
SqlDataReader dr;
cmd.Connection = Connections.Connection[Session["UserName"].ToString()];
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "CheckLogin_sp";
cmd.Parameters.AddWithValue("option", "GetDetails".Trim());
cmd.Parameters.AddWithValue("UserName", txtUserName.Text);
cmd.Parameters.AddWithValue("Pwd", txtPassword.Text);
dr = cmd.ExecuteReader();
while (dr.Read())
{
Session["Name"] = dr["name"].ToString();
Session["CompanyName"] = dr["CompanyName"].ToString();
Session["UserId"] = dr["Id"].ToString();
Session["Center"] = dr["Center"].ToString();
Session["ClientCode"] = dr["ClientCode"].ToString();
Session["UserImage"] = dr["Image"].ToString();
Session["CurrentDatabase"] = dr["CurrentDatabase"].ToString();
Session["UserName"] = txtUserName.Text;
Connections.BillReport = dr["BillReport"].ToString();
Connections.DuesReport = dr["DuesReport"].ToString();
Connections.GeneralReport = dr["GeneralReport"].ToString();
Connections.PendingReport = dr["PendingReport"].ToString();
Connections.RadiologyReport = dr["RadiologyReport"].ToString();
Connections.HistoReport = dr["HistoReport"].ToString();
}
cmd.Parameters.Clear();
cmd.Dispose();
dr.Close();
}
Note:- When I check temporary files in my computer I found 6 GB temporary files in just 15 days. Is it because of heavy load of temporary files ? or something wrong in my Code ?
Can anyone tell me what I am doing wrong here ?
Try:
while (dr.Read() != null)
IndexOutOfRange exception is thrown when you attempt to access (Read/ Write) an element of an array with an index which is outside the bounds of the array
As per your problem, I guess you are trying to read or write some array elements which are outside of your array boundary.
for example:
It's error related when you are retriving index record which is not exist.
See if there's 5 elements in array, But when you are trying to retrieve record at index 6 then it will generate Exception of kind IndexOutOfRangeException.
See here HERE for more details.
You can try this code:
while (dr.Read() != null){
// code goes here.
}
OR
while(dr.Read() != ''){
// code goes here.
}
If not solved, you must be debug your program.

checking user name or user email already exists

I am working in a simple registration page where the user can't enter the same user name or email, I made a code that prevent the user from entering the username and it worked but when I tried to prevent the user from entring the same username or email it didn't work.
and my question is, "How can I add another condition where the user can't enter email that already exists?"
I tried to do it in this code, but it did't work:
protected void Button_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection( ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString );
SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =#UserName", con);
SqlCommand cmd2 = new SqlCommand("select 1 from Table where Email=#UserEmail", con);
con.Open();
cmd1.Parameters.AddWithValue("#UserName", Name_id.Text);
cmd2.Parameters.AddWithValue("#UserEmail", Email_id.Text);
using (var dr1 = cmd1.ExecuteReader())
{
if (dr1.HasRows)
{
Label1.Text = "user name already exists";
}
using (var dr2 = cmd2.ExecuteReader())
{
if (dr2.HasRows)
{
Label1.Text = "email already exists";
}
else
{
dr1.Close();
dr2.Close();
//add new users
con.Close();
}
}
}
}
but i get this error:
There is already an open DataReader associated with this Command which must be closed first.
Like I said in my comment your design is bad !
First you should have Data Access Layer. This should be project in big solutions but in your case you can put it like new directory. In this directory you create SqlManager class here is the code:
public class SqlManager
{
public static string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["DevConnString"].ConnectionString;
}
}
public static SqlConnection GetSqlConnection(SqlCommand cmd)
{
if (cmd.Connection == null)
{
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
cmd.Connection = conn;
return conn;
}
return cmd.Connection;
}
public static int ExecuteNonQuery(SqlCommand cmd)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static object ExecuteScalar(SqlCommand cmd)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteScalar();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static DataSet GetDataSet(SqlCommand cmd)
{
return GetDataSet(cmd, "Table");
}
public static DataSet GetDataSet(SqlCommand cmd, string defaultTable)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
DataSet resultDst = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(resultDst, defaultTable);
}
return resultDst;
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static DataRow GetDataRow(SqlCommand cmd)
{
return GetDataRow(cmd, "Table");
}
public static DataRow GetDataRow(SqlCommand cmd, string defaultTable)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
DataSet resultDst = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(resultDst, defaultTable);
}
if (resultDst.Tables.Count > 0 && resultDst.Tables[0].Rows.Count > 0)
{
return resultDst.Tables[0].Rows[0];
}
else
{
return null;
}
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
}
After that you should have Business Object Layer. In bigger solution is project in your case directory. If you are in the page TaxesEdit.aspx, you should add Tax.cs class in the BO(business object).
Example of methods for the class, for your first button:
public DataSet GetTaxesByUserName(string userName)
{
SqlCommand cmd = new SqlCommand(#"
select 1 from Table where Name =#UserName");
cmd.Parameters.AddWithValue("#UserName", userName);
return DA.SqlManager.GetDataSet(cmd);
}
You fetch all the needed data in datasets. After that you make checks like taxesDst.Tables[0].Rows.Count > 0 (or == 0)
For Insert you can have method like this:
public virtual void Insert(params object[] colValues)
{
if (colValues == null || colValues.Length % 2 != 0)
throw new ArgumentException("Invalid column values passed in. Expects pairs (ColumnName, ColumnValue).");
SqlCommand cmd = new SqlCommand("INSERT INTO " + TableName + " ( {0} ) VALUES ( {1} )");
string insertCols = string.Empty;
string insertParams = string.Empty;
for (int i = 0; i < colValues.Length; i += 2)
{
string separator = ", ";
if (i == colValues.Length - 2)
separator = "";
string param = "#P" + i;
insertCols += colValues[i] + separator;
insertParams += param + separator;
cmd.Parameters.AddWithValue(param, colValues[i + 1]);
}
cmd.CommandText = string.Format(cmd.CommandText, insertCols, insertParams);
DA.SqlManager.ExecuteNonQuery(cmd);
}
For this you need to have property TableName in the current BO class.
In this case this methods can be used everywhere and you need only one line of code to invoke them and no problems like yours will happen.
You have opened another DataReader inside the First and thats causing the problem. Here I have re-arranged your code a bit
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =#UserName", con),
cmd2 = new SqlCommand("select 1 from Table where Email=#UserEmail", con);
con.Open();
cmd1.Parameters.AddWithValue("#UserName", Name_id.Text);
cmd2.Parameters.AddWithValue("#UserEmail", Email_id.Text);
bool userExists = false, mailExists = false;
using (var dr1 = cmd1.ExecuteReader())
if (userExists = dr1.HasRows) Label1.Text = "user name already exists";
using (var dr2 = cmd2.ExecuteReader())
if (mailExists = dr2.HasRows) Label1.Text = "email already exists";
if (!(userExists || mailExists)) {
// can add User
}
You need to close one datareader before opening the other one. Although it's not how I'd do it, but you can deal with the runtime error by closing the datareader after each IF:
using (var dr1 = cmd1.ExecuteReader())
{
if (dr1.HasRows)
{
string Text = "user name already exists";
}
dr1.Close();
}
using (var dr2 = cmd2.ExecuteReader())
{
if (dr2.HasRows)
{
string ext = "email already exists";
}
else
{
//add new users
}
dr2.Close();
}
con.Close();
This may work, although there are a few things I would do differently...
protected void Button_Click(object sender, EventArgs e)
{
bool inputIsValid = true;
var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
var userNameCmd = new SqlCommand("SELECT 1 FROM Table WHERE Name = #UserName", con);
var emailCmd = new SqlCommand("SELECT 1 FROM Table WHERE Email = #UserEmail", con);
con.Open();
userNameCmd.Parameters.AddWithValue("#UserName", Name_id.Text);
emailCmd.Parameters.AddWithValue("#UserEmail", Email_id.Text);
using (var userNameReader = userNameCmd.ExecuteReader())
{
if (userNameReader.HasRows)
{
inputIsValid = false;
Label1.Text = "User name already exists";
}
}
using (var emailReader = emailCmd.ExecuteReader())
{
if (emailReader.HasRows)
{
inputIsValid = false;
Label1.Text = "Email address already exists";
}
}
if (inputIsValid)
{
// Insert code goes here
}
con.Close();
}
Why don't you do something like this:
[Flags]
public enum ValidationStatus
{
Valid = 0 ,
UserNameInUse = 1 ,
EmailInUse = 2 ,
}
public ValidationStatus ValidateUser( string userName , string emailAddr )
{
ValidationStatus status ;
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString ;
using ( SqlConnection con = new SqlConnection( connectionString ) )
using ( SqlCommand cmd = con.CreateCommand() )
{
cmd.CommandText + #"
select status = coalesce( ( select 1 from dbo.myTable t where t.UserName = #UserName ) , 0 )
+ coalesce( ( select 2 from dbo.myTable t where t.UserEmail = #UserEmail ) , 0 )
" ;
cmd.Parameters.AddWithValue( "#UserName" , userName ) ;
cmd.Parameters.AddWithValue( "#emailAddr" , emailAddr ) ;
int value = (int) cmd.ExecuteScalar() ;
status = (ValidationStatus) value ;
}
return status ;
}
Aside from anything else, hitting the DB twice for something like this is silly. And this more clearly expresses intent.
Then you can use it in your button click handler, something like this:
protected void Button_Click( object sender , EventArgs e )
{
string userName = Name_id.Text ;
string emailAddr = Email_id.Text ;
ValidationStatus status = ValidateUser( userName , emailAddr ) ;
switch ( status )
{
case ValidationStatus.Valid :
Label1.Text = "" ;
break ;
case ValidationStatus.EmailInUse :
Label1.Text = "Email address in use" ;
break ;
case ValidationStatus.UserNameInUse :
Label1.Text = "User name in use" ;
break ;
case ValidationStatus.EmailInUse|ValidationStatus.UserNameInUse:
Label1.Text = "Both user name and email address in use." ;
break ;
default :
throw new InvalidOperationException() ;
}
if ( status == ValidationStatus.Valid )
{
CreateNewUser() ;
}
}

asp.net database connectivity

Please take a look at the following code.
protected void Button2_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(constring);
SqlCommand cmd = new SqlCommand();
if (DropDownList3.SelectedItem.Text == "Economy")
{
seats = Convert.ToInt32(DropDownList1.SelectedItem.Text);
cmd.Connection = con;
con.Open();
cmd.CommandText = "select easeats from flight where fno='" + fn + "'";
int eds = Convert.ToInt32(cmd.ExecuteScalar());
if (eds > seats)
{
Panel2.Visible = true; //seats available
cl = DropDownList3.SelectedItem.Text;
seat = seats.ToString();
seats = eds;
}
else
{
Panel3.Visible = true; // seats not available
}
con.Close();
}
}
I am getting error in the line:int eds = Convert.ToInt32(cmd.ExecuteScalar());
And the error is
error in converting varchar value to datatype int
What is wrong with this code?
Firstly, NEVER construct your query like this. Use parameterized queries instead.
Secondly, the error message is quite clear - you're trying to convert to int some varchar column, that probably contains some literal characters as well and not only numbers...
Thirdly, prefer "using" statements over explicitly closing the connection. It's more safe that way.
try to replace:
int eds = Convert.ToInt32(cmd.ExecuteScalar());
with:
int eds = 0;
int.TryParse(cmd.ExecuteScalar(), out eds);
in this way if the Convert fails you have no issues and continue with eds = 0...
side note, your handling of exceptions and connection lifetime is very poor, think about replacing the whole block in this way:
protected void Button2_Click(object sender, EventArgs e)
{
using(var con = new SqlConnection(constring))
using(var cmd = con.CreateCommand())
{
if (DropDownList3.SelectedItem.Text == "Economy")
{
seats = Convert.ToInt32(DropDownList1.SelectedItem.Text);
con.Open();
cmd.CommandText = "select easeats from flight where fno='" + fn + "'";
int eds = 0;
object result = cmd.ExecuteScalar();
int.TryParse(result, out eds);
if (eds > seats)
{
Panel2.Visible = true; //seats available
cl = DropDownList3.SelectedItem.Text;
seat = seats.ToString();
seats = eds;
}
else
{
Panel3.Visible = true; // seats not available
}
}
}
}
of course, anyway, you should also consider to refactor the whole thing and separate clearly database and business logic from UI logic, in general you should never deal directly with connections and queries inside the UI and even less in a ButtonClick event handler.

Categories