I'm making a login system currently and I would like to present feedback when the username or the password are incorrect.
Here is the content of the text file from which I'm reading the details:
Ryan:password
Username:password
When I enter Ryan and password, it works fine and brings me to the next form.
However, when I enter Username and password, it comes up with the 'Username Incorrect' message box first, and then after I close out of that message box, it brings me to the next form.
I would like it to bring me directly to the next form without showing the Username Incorrect MessageBox first, even if I do enter the details on the second line. There would be more lines in the text file in the future.
Any help would be greatly appreciated, thanks!
Here is the code:
private void button1_Click(object sender, EventArgs e)
{
string[] userdetails = File.ReadAllLines(AppDomain.CurrentDomain.BaseDirectory + "UserDetails.txt");
foreach (string user in userdetails)
{
string[] splitDetails = user.Split(':');
Login.username = splitDetails[0];
Login.password = splitDetails[1];
label1.Text = Login.username;
label2.Text = Login.password;
if ((txtUsername.Text == Login.username) && (txtPassword.Text == Login.password))
{
MessageBox.Show("Welcome " + Login.username);
this.Hide();
frmMainMenu menu = new frmMainMenu();
menu.Show();
break;
}
else
{
if ((txtUsername.Text == Login.username) && (txtPassword.Text != Login.password))
{
MessageBox.Show("Password incorrect");
break;
}
if(txtUsername.Text != Login.username)
{
MessageBox.Show("Username incorrect");
}
}
}
}
The logic is incorrect.
Ask yourself, when should you stop going through your list of credentials?
Assuming a username is unique, I see only one situation that could break your loop, and that is "the username has been found".
As soon as you find the input username in your list, you know the loop has to break. You then only have to check whether the password is correct or not.
If the password is correct, you can open your new window and return your function, it has done its job.
And after the loop, you put your MessageBox, with a message depending on if the username has been found or not.
private void button1_Click(object sender, EventArgs e)
{
string[] userdetails = File.ReadAllLines(AppDomain.CurrentDomain.BaseDirectory + "UserDetails.txt");
bool usernameFound = false;
foreach (string user in userdetails)
{
string[] splitDetails = user.Split(':');
Login.username = splitDetails[0];
Login.password = splitDetails[1];
label1.Text = Login.username;
label2.Text = Login.password;
if (txtUsername.Text == Login.username)
{
if (txtPassword.Text == Login.Password)
{
MessageBox.Show("Welcome " + Login.username);
this.Hide();
frmMainMenu menu = new frmMainMenu();
menu.Show();
return; // we're done here, so return instead of break
}
usernameFound = true;
break; // we're not gonna find this username again, so might as well quit the loop
}
}
//we only get there if the credentials were incorrect
//so we check if the username was found, if yes, the
//password was incorrect, if not, the username was
string message = String.Empty;
if (usernameFound)
message = "Password";
else
message = "Username";
message += " incorrect";
MessageBox.Show(message);
//or shorten the above 7 lines with a ternary operator
//MessageBox.Show((usernameFound ? "Password" : "Username") + " incorrect");
}
In your senario if you had 100 users (user1..user100)
your code reads
for each line in file
check if matches
if yes make new form
else complain it isnt a match
So for user100, 99 its not a match messages will appear one for each non match before it.
You would need to code it like this
isfound=false
for each line in file
check if match
if yes set isfound and break
if isfound
show form blah
else
whine not found
Related
I am working on a project and I am trying to get my Navigation button to recognise when values already stored are cleared from the clear all fields button made. Its fine when I do not enter any values the first time but if I type them in and store them then clear all fields I press the navigation button then I progress onto the window without entering any details. Is there a way to solve this?
here is my code:
thank you.
private void clear_Click(object sender, RoutedEventArgs e)
{
//clears all fields to start again on enetring your details
if (SCNResult.Text == String.Empty || Nameresult.Text == String.Empty)
{
MessageBox.Show("You need to enter your details and store them before pressing this button");
return;
}
Nameresult.Text = " ";
box.Text = "";
namebox.Text = "";
SCNResult.Text = " ";
error.Text = " ";
//
}
/////END OF BUTTON////
private void comp_Click(object sender, RoutedEventArgs e)
{
// This instruction stops the user from continuing if they have not entered their details.
if (SCNResult.Text == String.Empty || Nameresult.Text == String.Empty)
{
MessageBox.Show("You need to enter your details before progressing to the next window");
return;
}
else
{
computing Nav1 = new computing();
Nav1.Show();
this.Close();
}
//end of instruction
//navigates to the next window
//
}
When you clear the fields:
Nameresult.Text = " "; //here is the problem
box.Text = "";
namebox.Text = "";
SCNResult.Text = " "; //here is the problem
error.Text = " ";
" " is not an empty string, that's why your if always return false
I've been messing around for over an hour now. I still don't know how to solve it even reading the Stackoverflow solution. The program works with the first username and password (test & password), when I typed in the second username and password (aaa & 123) it doesn't work.
public partial class Form2 : Form
{
String[] username = { "test", "aaa" };
String[] password = { "password", "123" };
private void btnSubmit_Click(object sender, EventArgs e)
{
try
{
for (int i = 0; i < username.Length; i++) // <------- Unreachable Code
{
if ((txtUsername.Text.Trim() == username[i]) && (txtPassword.Text.Trim() == password[i]))
{
MessageBox.Show("Login Successful. Welcome!", "Login Success", MessageBoxButtons.OK, MessageBoxIcon.None);
Form3 frm3 = new Form3();
frm3.Visible = true;
frm3.Activate();
break;
}
else
{
MessageBox.Show("You have entered an invalid input. Do you want to try again?", "Invalid Input", MessageBoxButtons.YesNo, MessageBoxIcon.Hand); break;
}
}
}
catch(Exception x)
{
MessageBox.Show("System Error! Please try again!", "System Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
}
}
You have break word in both if-else branches. Remove break from else. But you will get message boxes on every loop. So you need to modify your code: move message box outside the loop.
You have logical flow control issues inside of your code. As a result, you need to move the MessageBox firing outside of your loop.
If you modify your code to use lists instead of arrays and include a bit of LINQ, you can move away from a loop altogether, as well as you can benefit from less nesting.
public partial class Form2 : Form
{
List<string> username = new List<string>{ "test", "aaa" };
List<string> password = new List<string>{ "password", "123" };
private void btnSubmit_Click(object sender, EventArgs e)
{
try
{
if (txtUsername.Text.Length > 0 && txtPassword.Text.Length > 0
&& username.Any(x => x == txtUsername.Text.Trim())
&& password.Any(x => x == txtPassword.Text.Trim()))
{
MessageBox.Show(
"Login Successful. Welcome!",
"Login Success", MessageBoxButtons.OK, MessageBoxIcon.None);
Form3 frm3 = new Form3();
frm3.Visible = true;
frm3.Activate();
}
else
{
MessageBox.Show(
"You have entered an invalid input. Do you want to try again?",
"Invalid Input",
MessageBoxButtons.YesNo, MessageBoxIcon.Hand);
}
}
catch(Exception x)
{
MessageBox.Show(
"System Error! Please try again!", "System Error",
MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
}
}
I'm new about C#, I learnt C programmation for one year now.
I created a Window Form which asks the user to complete a registration form.
My registration form
I'd like to display an error message below the buttons when a field is not filled or a field isn't well used.
I used this basic code :
private void button1_Click(object sender, EventArgs e)
{
if (!isOkay(userTextBox.Text))
{
label5.Text = "Please, enter an username.";
label5.Visible = true;
}
else if (!isOkay(mailTextBox.Text))
{
label5.Text = "Please, enter a mail address.";
label5.Visible = true;
}
else if (!confirmMailTextBox.Text.Equals(mailTextBox.Text) || !isOkay(confirmMailTextBox.Text))
{
label5.Text = "Please, match both mails addresses.";
label5.Visible = true;
}
else if (!isOkay(passwordTextBox.Text))
{
label5.Text = "Please, enter a password.";
label5.Visible = true;
}
else
{
label5.Text = "Valid form, yay !";
label5.Visible = true;
}
}
private Boolean isOkay(string textBoxContent)
{
return (textBoxContent.Length > 0 || textBoxContent.Equals(null));
}
Are there any elegant or optimized ways to do it properly ? I found some Error providers, but apparently error providers open a pop-up, and I just want a "red error message below buttons".
Can you give me some help ? :)
Given a class like this
public class RequiredFieldsError
{
private List<string> errors;
public RequiredFieldsError()
{
errors = new List<string>();
}
public int Count
{
get{return errors.Count;}
}
public void AddField(string errorField)
{
errors.Add(errorField);
}
public override string ToString()
{
if(errors.Count == 0)
return string.Empty;
else
{
string fields = string.Join(Environment.NewLine, errors);
fields = "The following fields contains errors:" + Environment.NewLine + fields;
return fields;
}
}
}
then you could change your code to
private void button1_Click(object sender, EventArgs e)
{
RequiredFieldsError rfe = new RequiredFieldsError();
if (!isOkay(userTextBox.Text))
rfe.AddField("User name missing, Please, enter an username.";
if (!isOkay(mailTextBox.Text))
rfe.AddField("Email address missing, Please, enter a mail address.";
if (!confirmMailTextBox.Text.Equals(mailTextBox.Text) || !isOkay(confirmMailTextBox.Text))
rfe.AddField("Email address doesn't match the confirmation email");
if (!isOkay(passwordTextBox.Text))
rfe.AddField("Password missing, Please, enter a password.";
if(rfe.Count > 0)
{
// MessageBox.Show(rfe.ToString());
label5.Text = rfe.ToString()
label5.Visible = true;
}
}
This approach avoids the unnerving situation (for your user) when he/she receives an error message, he/she fixes it just to receive another error message at the next attempt to confirm the form.
Of course your label should be tall enough to show all the possible messages or just use a messagebox.
I suggest also to change your IsOkay function to
private Boolean isOkay(string textBoxContent)
{
return !string.IsNullOrWitheSpace(textBoxContent));
}
this will handle also a string composed just of one or more spaces. (not null and not length==0)
You can use ErrorProvider. It show's an error icon after your textbox.
For one of your textboxes for example:
if (!isOkay(userTextBox.Text))
{
errorProvider1.SetError(userTextBox "yourmessage");
}
else{
errorProvider1.Clear();
}
Link: http://www.dotnetperls.com/errorprovider
I have a sql data base with column for username and password.
I made login form which is asking the user to enter a valid username and password.
The check for a wrong entry already works but the check when the username password combination is ok fails.
namespace Kartice
{
public partial class Pass : Form
{
Matjaz Matjaz = new Matjaz();
public Pass()
{
// string myconnection = #"C:\Users\Bojan\Desktop\Programiranje\School\Kartice\Kartice\Users.mdf";
InitializeComponent();
}
private void usersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.usersBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.usersDataSet);
}
private void Pass_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'usersDataSet.Users' table. You can move, or remove it, as needed.
this.usersTableAdapter.Fill(this.usersDataSet.Users);
}
private void BtnOk_Click(object sender, EventArgs e)
{
if (Imetxt.Text == "")
{
MessageBox.Show("Please enter a valid user name!");
Imetxt.Focus();
}
else if (Passtxt.Text == "")
{
MessageBox.Show("Please enter a valid password!");
Passtxt.Focus();
}
string userName1, userPassword1;
userName1 = Imetxt.Text;
userPassword1 = Passtxt.Text;
foreach (DataRow row in usersDataSet.Users)
{
if (row["Ime_Priimek"].ToString() == userName1)
{
if (row["Password"].ToString() == userPassword1)
{
Pass myForm1 = new Pass();
Matjaz myForm2 = new Matjaz();
myForm2.Show();
myForm1.Hide();
break;
}
}
else
MessageBox.Show("You have entered a wrong user name or the password!");
}
}
The MessageBox is inside the for loop.
Let's assume we have 5 users in the table.
Let's assume I entered luke for the username, and the correct password.
=======================
| Username | Password |
|- - - - - | - - - - -|
| matthew | ***** |
| mark | ***** |
| luke | ***** |
| john | ***** |
=======================
Username luke is third in this table.
Here is the what your program does, in plain-English:
<<start>>
Is 'matthew' equal to 'luke'?
- No! Display a message box.
Is 'mark' equal to 'luke'?
- No! Display a message box.
Is 'luke' equal to 'luke'?
- Yes!
- Is '****' equal to '****'?
- Yes! Show Form2 and hide Form1.
<<end>>
Hopefully, the problem is clear now. The first thing you need to do is move the MessageBox out of the for loop.
bool userFound = false;
foreach (DataRow row in usersDataSet.Users)
{
if (row["Ime_Priimek"].ToString() == userName1)
{
if (row["Password"].ToString() == userPassword1)
{
userFound = true;
Pass myForm1 = new Pass();
Matjaz myForm2 = new Matjaz();
myForm2.Show();
myForm1.Hide();
break;
}
}
}
if (!userFound)
{
MessageBox.Show("You have entered a wrong user name or the password!");
}
Ignoring all the other problems with plaintext passwords and downloading the database to the client etc....
Your message box is inside the for loop, so every user that doesn't match will show the MessageBox....
Changing the for loop to
foreach (DataRow row in usersDataSet.Users)
{
if (row["Ime_Priimek"].ToString() == userName1 && row["Password"].ToString() == userPassword1)
{
Pass myForm1 = new Pass(); // Don't think you need this.
Matjaz myForm2 = new Matjaz();
myForm2.Show();
myForm1.Hide(); // shouldn't this be this.Hide();
return;
}
}
}
MessageBox.Show("You have entered a wrong user name or the password!");
UPDATE
Inline with other comments/answers
To prevent the user check carrying on when either username or password is empty insert a return statement after each focus call. It won't make a difference to your existing problem the above code fixes that, but I think its closer to your intended execution. e.g.
if (Imetxt.Text == "")
{
MessageBox.Show("Please enter a valid user name!");
Imetxt.Focus();
return;
}
else if (Passtxt.Text == "")
{
MessageBox.Show("Please enter a valid password!");
Passtxt.Focus();
return;
}
So i try to create a sign up method using entity framework and c#, this is the method :
//Button create new account
private void BtnSignUp_Click(object sender, EventArgs e)
{
IEnumerable<DriverAcount> list = from a in context.DriverAcounts select a;
foreach (var Ac in list)
{
if (TxBoxNewUserName.Text != Ac.Login)
{
if (TxtBoxPASS1.Text == TxBoxPass.Text)
{
Ac.Login = TxBoxNewUserName.Text;
Ac.Password = TxtBoxPASS1.Text;
context.DriverAcounts.Add(Ac);
MessageBox.Show("the account is create succefuly");
TxBoxNewUserName.Text = "";
TxtBoxPASS1.Text = "";
TxBoxPass.Text = "";
break;
}
else
{
MessageBox.Show("the two passwords didn't matched");
}
TxBoxNewUserName.Text = "";
TxtBoxPASS1.Text = "";
TxBoxPass.Text = "";
continue;
}
else
{
MessageBox.Show("this username is already exist, please choose another one");
TxBoxNewUserName.Text = "";
TxtBoxPASS1.Text = "";
TxBoxPass.Text = "";
break;
}
}
context.SaveChanges();
}
the problem is when i want to add a new user normally it should looking if it exist in database or not, but it didn't do it right, for example if we have two names in DB name1 and name2 and into the TextBox we have name2 it will add the name2 in DB even if it is already exist.
So plz if someone have an idea i will be very appreciate.
You need to look at your code again and understand exactly what it's doing - have you attached the debugger and stepped through it? The driver name will always be created on the first iteration of the foreach loop if the first name retrieved doesn't match the one in the text box. All the others will be ignored.
You can try this instead. There's no need querying for all the records (like you're doing at the moment) when you only want to check if one already exists.
private void BtnSignUp_Click(object sender, EventArgs e)
{
// This performs a case sensitive match on the login name, you'll need to change it if you want to ignore case
DriverAcount existingAccount = context.DriverAcounts.FirstOrDefault(d => d.Login == TxBoxNewUserName.Text);
if (existingAccount != null)
{
MessageBox.Show("This username already exists, please choose another one.");
}
else
{
if (TxtBoxPASS1.Text == TxBoxPass.Text)
{
Ac.Login = TxBoxNewUserName.Text;
Ac.Password = TxtBoxPASS1.Text;
context.DriverAcounts.Add(Ac);
// Only need to call this if you've made changes, so I've moved it here
context.SaveChanges();
MessageBox.Show("The account was created successfully");
}
else
{
MessageBox.Show("The two passwords didn't match each other.");
}
}
TxBoxNewUserName.Text = "";
TxtBoxPASS1.Text = "";
TxBoxPass.Text = "";
}