i am writing C# function now, which must return me user password. All is fine, but than i am trying to compile this project, VS telling me about unassigned variable.
string sqlLoginCheck (string userId)
{
string database, host, user, pass, sqlParams, sqlQuery;
string resultPassword;
database = "db";
host = "localhost";
user = "root";
pass = "....";
sqlParams = "Database=" + database + ";Data Source=" + host + ";User Id=" + user + ";Password=" + pass;
sqlQuery = "SELECT `id`, `name`, `pass` FROM `users` WHERE name = '" + userId + "' LIMIT 1";
MySqlConnection sqlConnection = new MySqlConnection(sqlParams);
MySqlCommand sqlCommand = new MySqlCommand(sqlQuery, sqlConnection);
// Выполняем
try
{
sqlConnection.Open();
MySqlDataReader sqlReader = sqlCommand.ExecuteReader();
if (sqlReader.HasRows)
{
while (sqlReader.Read())
{
resultPassword = sqlReader[2].ToString();
}
}
else
{
resultPassword = "";
}
}
catch (MySqlException sqlError)
{
errorMessage.Text = "Ошибка: " + sqlError.Message;
FileInfo errorLog = new FileInfo("errorLog.txt");
if (errorLog.Exists == false)
{
FileStream errorFs = errorLog.Create();
errorFs.Close();
}
StreamWriter errorSw = errorLog.AppendText();
errorSw.WriteLine(DateTime.Now + " | " + sqlError.Message);
errorSw.Close();
}
finally
{
sqlConnection.Close();
}
return resultPassword;
}
Here i can't return resultPassword, because variable is unassigned :|
Declare this variable as
string resultPassword = null;
Or you can declare it as
string resultPassword = String.Empty;
in that case you don't really need
else
{
resultPassword = "";
}
because default value for password has already been set at declaration.
The resultPassword is declared in the function body, but it is initialized only inside the try block: so in case of exception, the variable will be unassigned.
Initialize the variable outside the try-catch block.
Some details here.
The compiler sees that there is a chance that resultPassword never gets assigned (if you go into the Catch or Finally. Just do :
string resultPassword = "";
in the declaration
It's because there is a root through the method where resultPassword is never assigned a value. As others have said declare:
string resultPassword = null;
I would suggest
string resultPassword = "";
then if you need to set to not found, actually set it to say "** not found **" or something. As it stands you have paths down your code where the variable isnt set - eg it enters the catch area.
Related
So I know this is a often asked question but I want to check if the username is already taken in the database using c#. I tried this:
MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM tablename WHERE(name = '" + tb1.Text + "');");
cmd2.Connection = connect;
connect.Open();
string unt = "";
try
{
MySqlDataReader dr;
dr = cmd.ExecuteReader();
while (dr.Read())
{
unt= dr.GetString("name");
}
dr.Close();
}
catch (Exception ex)
{
errorbox.Content = ex.Message;
}
finally
{
connect.Close();
}
if(unt == "" || unt == "0") {
continuel = false;
tb2.Text = "User " +tb1.Text+ " doesn't exist!";
Popup1.IsOpen = true;
}
Its a WPF project and the variable 'continuel' is set to true by default. The code doesn't recognize if a user doesn't exist.
First off your code is vulnerable to sql inject, you should never concatenate values into a query. secondly you can do a count and execute a scalar. Not I stripped down your code a little you'll have to add error handling back.
bool userExists = false;
private String sql = "SELECT COUNT(*) FROM tableName WHERE name = #usernameparam;";
MySqlCommand m = new MySqlCommand(sql);
m.Parameters.AddWithValue("#usernameparam", tb1.Text.Trim());
int userCount = Convert.ToInt32(m.ExecuteScalar());
if(userCount>0)
{
userExists = true;
}
//use userExists variable to evaluate if user exists
My MySQL connection throws null reference although this code worked well one year ago.
The line where the debugger indicates the exception contains
"connection = new MySqlConnection(connectionString);":
DBConnect MySqlConnection = new DBConnect();
string[] resultArray = MySqlConnection.GetValidUser(
"tbl_user",
tbEmail.Text,
tbPassword.Text
);
//THROWS null reference exception in method 'private bool OpenConnection()'
//A first chance exception of type 'System.ArgumentException' occurred in System.Data.dll
This is my DBConnect class:
class DBConnect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
public DBConnect()
{
server = "x.x.x.x";
database = "...";
uid = "...";
password = "...";
string connectionString = "SERVER=" + server + ";" +
"DATABASE=" + database + ";" +
"UID=" + uid + ";" +
"PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Cannot connect to MySQL server.");
break;
case 1045:
MessageBox.Show("Invalid username or password.");
break;
}
return false;
}
}
public string[] GetValidUser(string dbTable, string dbUsername, string dbPassword)
{
string query = "SELECT id,email,password FROM " + dbTable +
" WHERE email='" + dbUsername +
"' AND password='" + dbPassword + "'";
string[] resultArray = new string[3];
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
}
dataReader.Close();
this.CloseConnection();
}
return resultArray;
}
}
The original code for the database class can be found here.
This is not an answer to the NullReferenceException - we're still working through that in the comments; this is feedback for the security parts.
The first thing we can look at is SQL injection; this is very easy to fix - see below (note I've tidied some other things too)
// note: return could be "bool" or some kind of strongly-typed User object
// but I'm not going to change that here
public string[] GetValidUser(string dbUsername, string dbPassword)
{
// no need for the table to be a parameter; the other two should
// be treated as SQL parameters
string query = #"
SELECT id,email,password FROM tbl_user
WHERE email=#email AND password=#password";
string[] resultArray = new string[3];
// note: it isn't clear what you expect to happen if the connection
// doesn't open...
if (this.OpenConnection())
{
try // try+finally ensures that we always close what we open
{
using(MySqlCommand cmd = new MySqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("email", dbUserName);
// I'll talk about this one later...
cmd.Parameters.AddWithValue("password", dbPassword);
using(MySqlDataReader dataReader = cmd.ExecuteReader())
{
if (dataReader.Read()) // no need for "while"
// since only 1 row expected
{
// it would be nice to replace this with some kind of User
// object with named properties to return, but...
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
if(dataReader.Read())
{ // that smells of trouble!
throw new InvalidOperationException(
"Unexpected duplicate user record!");
}
}
}
}
}
finally
{
this.CloseConnection();
}
}
return resultArray;
}
Now, you might be thinking "that's too much code" - sure; and tools exist to help with that! For example, suppose we did:
public class User {
public int Id {get;set;}
public string Email {get;set;}
public string Password {get;set;} // I'll talk about this later
}
We can then use dapper and LINQ to do all the heavy lifting for us:
public User GetValidUser(string email, string password) {
return connection.Query<User>(#"
SELECT id,email,password FROM tbl_user
WHERE email=#email AND password=#password",
new {email, password} // the parameters - names are implicit
).SingleOrDefault();
}
This does everything you have (including safely opening and closing the connection), but it does it cleanly and safely. If it method returns a null value for the User, it means no match was found. If a non-null User instance is returned - it should contain all the expected values just using name-based conventions (meaning: the property names and column names match).
You might notice that the only code that remains is actually useful code - it isn't boring plumbing. Tools like dapper are your friend; use them.
Finally; passwords. You should never store passwords. Ever. Not even once. Not even encrypted. Never. You should only store hashes of passwords. This means that you can never retrieve them. Instead, you should hash what the user supplies and compare it to the pre-existing hashed value; if the hashes match: that's a pass. This is a complicated area and will require significant changes, but you should do this. This is important. What you have at the moment is insecure.
Among other things, it sounds like you have problems with the connection string - from comments:
While "connection = new MySqlConnection(); connection.ConnectionString = connectionString;" throws an exception the statement "connection = new MySqlConnection();" does not...
The difference here is simply: in the latter you aren't setting the connection string - so it sounds like your connection string is not correctly escaping the values (most likely, the password); you could try:
var cs = new DbConnectionStringBuilder();
cs["SERVER"] = server;
cs["DATABASE"] = database;
cs["UID"] = uid;
cs["PASSWORD"] = password;
var connectionString = cs.ConnectionString;
Having problem reading a value from my table in mysql, is the index value i cant read the value back no matter what. all i get is the initialized value of 0 i dont get any error because it return 0, if i run the query in the database it get the correct value. i tried to use executeScalar() but with the same result .
MySqlConnection conn = new MySqlConnection(MyConString);
ulong ukey=0;
try
{
string sql_users2 = "SELECT `key` FROM `permuser` WHERE `user` = '" + myuser + "' AND `code` = '" + mycode + "'";
MySqlCommand cmdSel2 = new MySqlCommand(sql_users2, conn);
conn.Open();
MySqlDataReader dr2 = cmdSel2.ExecuteReader();
dr2.Read();
ukey = dr2.GetUInt64(dr2.GetOrdinal("key"));
// MessageBox.Show("Sorry " + myuser + " already have access to " + mycode + ",\nIf this is an extension, search for the user which key is " + ukey + " and edit the end date.", "Duplicate User Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
dr2.Close();
dr2.Dispose();
}
catch (MySqlException ex) //catch 2
{
MessageBox.Show("catch ukey\nCan't connect to database\n" + ex.ToString());
}
conn.Close();
conn.Dispose();
You are returning a single value from your query, so you could use directly ExecuteScalar instead of ExecuteReader. (the link point to the description for SqlServer, but it is the same for MySql)
An important question to never forget is the usage of parameters instead of string concatenation.
What happen if your myuser or mycode variables contain a single quote? You get wrong results or syntax errors.
Of course, the main problem is the Sql Injection attack to never understimate.
using(MySqlConnection conn = new MySqlConnection(MyConString))
{
ulong ukey=0;
try
{
string sql_users2 = "SELECT `key` FROM `permuser` WHERE `user` = #usr AND `code` = #code";
MySqlCommand cmdSel2 = new MySqlCommand(sql_users2, conn);
conn.Open();
cmdSel2.Parameters.AddWithValue("#usr", myuser);
cmdSel2.Parameters.AddWithValue("#code", mycode);
object result = cmdSel2.ExecuteScalar();
if(result != null)
ukey = Convert.ToUInt64(result);
}
catch (MySqlException ex) //catch 2
{
MessageBox.Show("catch ukey\nCan't connect to database\n" + ex.ToString());
}
}
also I am a bit perplexed about your usage of UInt64. What kind of datatype is stored in the key column?
way is many simply:
ukey = (uint)dr2[0];
i have tried to insert the data by login to the system. my query doesn't have any error, but the exception has thrown by the run time as "Object reference not set to an instance of an object ". check my code and please correct me.
protected void Button1_Click(object sender, EventArgs e)
{
try
{
if (TextBox6.Text == " ")
{
string alertmessage = "";
alertmessage = "Username should not be blank";
this.CreateMessageAlert(this, alertmessage, "alertKey");
TextBox6.Focus();
}
else if (TextBox7.Text == " ")
{
string alertmessage = "";
alertmessage = "Username should not be blank";
this.CreateMessageAlert(this, alertmessage, "alertKey");
TextBox7.Focus();
}
else
{
string sq = "SELECT COUNT(*) FROM tbl_KKSUser WHERE Uname=#un and Password=#pas";
SqlCommand sd = new SqlCommand(sq, con);
SqlParameter unameparam;
unameparam = new SqlParameter("#un", SqlDbType.VarChar, 25);
unameparam.Value = TextBox6.Text;
sd.Parameters.Add(unameparam);
string original = TextBox7.Text.Trim();
string withhash = original;
b1 = Encoding.BigEndianUnicode.GetBytes(withhash);
encrypted = Convert.ToBase64String(b1);
SqlParameter passparam;
passparam = new SqlParameter("#pas", SqlDbType.VarChar, 8000);
passparam.Value = Convert.ToString(encrypted);
sd.Parameters.Add(passparam);
con.Open();
{
int iresults;
iresults = Convert.ToInt32(sd.ExecuteScalar().ToString());
if (iresults > 0)
{
string q = "insert into tbl_KKSMaterialRaise(MaterialCode,Source,Category,Population,StockInStores,Specification,PrearedBy,CheckedBy,ApprovedBy,CreatedDate) values(#mc,#sc,#cat,#pop,#sis,#spec,#pb,#cb,#ab,#cd)";
SqlCommand dm = new SqlCommand(q, con);
dm.Parameters.AddWithValue("#mc", Mcodeddl.SelectedItem.Text);
dm.Parameters.AddWithValue("#sc", TextBox1.Text.Trim());
dm.Parameters.AddWithValue("#cat", TextBox2.Text.Trim());
dm.Parameters.AddWithValue("#pop", TextBox3.Text.Trim());
dm.Parameters.AddWithValue("#sis", TextBox4.Text.Trim());
dm.Parameters.AddWithValue("#spec", TextBox5.Text.Trim());
dm.Parameters.AddWithValue("#pb", PBddl.SelectedItem.Text);
dm.Parameters.AddWithValue("#cb", CBddl.SelectedItem.Text);//In this line i have got error
dm.Parameters.AddWithValue("#ab", ABddl.SelectedItem.Text);
dm.Parameters.AddWithValue("#cd", DateTime.Today);
dm.ExecuteNonQuery();
string alertmessage = "";
alertmessage = "Component Details Saved";
this.CreateMessageAlert(this, alertmessage, "alertKey");
}
else
{
Response.Write("<script>alert('Invalid Username/Password')</script>");
}
}
con.Close();
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
It looks most likely that one of your dropdownlists has no option selected, i.e. the null reference is coming from one of the lines like:
dm.Parameters.AddWithValue("#mc", Mcodeddl.SelectedItem.Text);
Try checking that all of those have items selected before retrieving the .Text property.
If it isn't that, it would be useful to know which line is causing the exception - you can usually get that from the exception stack trace.
It means you have not initialized or assigned a variable. The debugger should tell you which variable specifically. Take a closer look at it. Then you only have to check that it is already initialized (= new Class()) or assigned (= instance).
You may want to take a look at this question.
Using SQL Membership Provider for ASP.NET membership. I'm using first.last as the username, which is created programmatically from the user details filled in on a form.
When user submits the form, I want to be able to check if the username exists, and change it to username1 if it does, check username1 exists, and make it username2 if it exists, etc. until it is a unique username.
I don't know how to do stored procedures, so I'm trying to use a SQLDataReader to check if username exists.
The problem is my loop. The logic is basically to set a boolean and keep looping and adding 1 to the counter, until it doesn't find a duplicate. I have stepped through this many times, and even when it sets the boolean to false, it keeps looping.
Ideas please?
Code behind:
protected void Membership_add()
{
SqlConnection con = new SqlConnection(connectionString);
string NewUserNameString = FirstName.Text + "." + LastName.Text;
//Check for duplicate aspnet membership name and add a counter to it if exists
// Check for valid open database connection before query database
bool match = true;
SqlDataReader _SqlDataReader = null;
string TestNameString = NewUserNameString;
string selectDupeString = "SELECT UserId FROM aspnet_Users WHERE UserName = '" + TestNameString + "'";
SqlCommand SQLdatareaderCmd = new SqlCommand(selectDupeString, con);
int UserNameCounter = 0;
con.Open();
while (match = true)
{
//Open the connection
try
{
//Read the table
_SqlDataReader = SQLdatareaderCmd.ExecuteReader();
}
catch (Exception ex)
{
lblDatareaderEx.Text = "An Exception occurred. " + ex.Message + " " + ex.GetType().ToString();
}
if (_SqlDataReader.HasRows)
{
//match = true;
//increase counter by 1 for each record found and change First.Name to First.Namex
TestNameString = NewUserNameString;
UserNameCounter = UserNameCounter + 1;
TestNameString = TestNameString + UserNameCounter.ToString();
_SqlDataReader.Close();
_SqlDataReader.Dispose();
selectDupeString = "SELECT UserId FROM aspnet_Users WHERE UserName = '" + TestNameString + "'";
SQLdatareaderCmd = new SqlCommand(selectDupeString, con);
}
else
{
// close sql reader
_SqlDataReader.Close();
_SqlDataReader.Dispose();
//get out of loop
match = false;
}
}
con.Close();
con.Dispose();
}
This line:
while (match = true)
does an assignment.
If you want your code to work you have to do a comparison:
while (match == true)
Or, since your variable is already a bool, you can just use the variable directly:
while(match)
At the moment you're setting match rather than comparing it's value.
Try setting while (match = true) to while (match == true)
If you break your code out into smaller blocks, the code becomes simpler and easer to read.
private string MembershipAddUser(string firstName, string lastName)
{
string username = firstName + "." + lastName;
int i = 0;
while (UserExists(username))
{
i++;
username = firstName + "." + lastName + i.ToString();
}
return username;
}
private bool UserExists(string username)
{
string sql = "SELECT COUNT(*) FROM dbo.aspnet_Users WHERE UserName = #UserName";
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("#UserName", username);
using (connection)
{
connection.Open();
int count = (int) command.ExecuteScalar();
return (count != 0);
}
}