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);
}
}
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
what I'am trying to do here is to select the connected people,
but I don't really know how to do this. I have x names on the Listbox.
I want to check for every name the login & logout times and if login is bigger then logout time, it types near the name "Connected", "not connected" on ListBox.
Thank you in advance .
foreach (var Item in listBoxControl2.Items)
{
try
{
SqlConnection sqlConnection = new SqlConnection(ConnectDatabase);
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = "Select login_time_value,logout_time_value ConnectionTime.dbo.Avalaible where name = '" + Item.ToString() +"'";
sqlConnection.Open();
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (true)
{
bool flag = sqlDataReader.Read();
if (!flag)
{
break;
}
DateTime login = sqlDataReader.GetDateTime(0);
DateTime logout = sqlDataReader.GetDateTime(1);
if (login > logout)
{
}
else
{
}
}
sqlDataReader.Close();
sqlConnection.Close();
}
catch
{
}
}
There are many things that could be changed in your code, but to answer just to your problem, I would change the loop to use a simple for loop so you could access directly the items in the listBox and change the text for the matched items.
for(x = 0; x < listBoxControl2.Items.Count; x++)
{
while(sqlDataReader.Read())
{
DateTime login = sqlDataReader.GetDateTime(0);
DateTime logout = sqlDataReader.GetDateTime(1);
if (login > logout)
{
listBoxControl2.Items[x] = listBoxControl2.Items[x] + " connected";
}
else
{
listBoxControl2.Items[x] = listBoxControl2.Items[x] + " logged off";
}
}
}
The problem with the foreach is that you get a copy of the string text, you have to replace the original and this is easier with a for loop.
About the other problems.
Where is the FROM clause in the command text?
Move the opening of the connection outside the loop.
Use the using statement to open/use/close/dispose the disposable
objects (Why?)
Use parameterized query when building command texts to pass to the
database engine (Why?)
So the updated code could be
string cmdText = "Select login_time_value,logout_time_value ConnectionTime.dbo.Avalaible " +
"FROM ??????????" +
"where name = #name";
using(SqlConnection sqlConnection = new SqlConnection(ConnectDatabase))
using(SqlCommand sqlCommand = new SqlCommand(cmdText, sqlConnection))
{
sqlCommand.Parameters.AddWithValue("#name", "dummy");
sqlConnection.Open();
for(x = 0; x < listBoxControl2.Items.Count; x++)
{
string name = listBoxControl2.Items[x].ToString();
sqlCommand.Parameters["#name"].Value = name;
using(SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
{
while(sqlDataReader.Read())
{
DateTime login = sqlDataReader.GetDateTime(0);
DateTime logout = sqlDataReader.GetDateTime(1);
if (login > logout)
{
listBoxControl2.Items[x] = name + " connected";
}
}
}
}
}
My question, which is similar to this one, is how can I use OracleDataReader to retrieve all the fields for a given record? Currently, I've been using this method, which returns only one column value at a time:
public string Select_File(string filename, string subdirectory, string envID)
{
Data_Access da = new Data_Access();
OracleConnection conn = da.openDB();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename ='" + filename + "'"
+ " AND Subdirectory = '" + subdirectory + "'"
+ " AND Environment_ID = '" + envID + "'";
cmd.CommandType = CommandType.Text;
string x;
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows) // file exists in DB
{
dr.Read();
x = dr.GetString(2).ToString(); // return baseline filename (index 2)
}
else
{
x = "New File";
}
cmd.Dispose();
da.CloseDB(conn);
return x;
}
I'm sure that this method is far from perfect and ppl will be quick to point that out (I was basically given it by my supervisor since I didn't have any prior experience in ASP.NET) but all I really care about is that it works. My question is: how can it be modified to return all the fields for a given record?
The fields will be of either VARCHAR2, CHAR, or DATE datatypes, (if that makes a difference) and some of these values may be null. I'm thinking I could convert them to strings and return them as a list?
if u want something like this:
List<User> lstUser = new List<User>();
string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
using (DBManager dbManager = new DBManager(connectionString))
{
try
{
dbManager.Open();
OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
while (dataReader.Read())
{
oUser = new User();
oUser.Id = Convert.ToInt32(dataReader["ID"]);
oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
oUser.UserName = Convert.ToString(dataReader["User_Name"]);
lstUser.Add(oUser);
}
dataReader.Close();
dataReader.Dispose();
}
catch
(Exception)
{
}
finally
{
dbManager.Close();
dbManager.Dispose();
}
To read all the data from the columns of the current row in a DataReader, you can simply use GetValues(), and extract the values from the array - they will be Objects, of database types.
Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
//read values[i]
}
MSDN - "For most applications, the GetValues method provides an efficient means for retrieving all columns, rather than retrieving each column individually."
Sorry for posting an answer to a very old question. As none of the answers are correct (either they have security issues or not checking for DBNull), I have decided to post my own.
public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
{
var sb = new StringBuilder();
//TODO: Check the parameters
const string connectionString = "user id=userid;password=secret;data source=" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";
const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename = :filename"
+ " AND Subdirectory = :subdirectory"
+ " AND Environment_ID = :envID"
+ " AND rownum<=1";
using (var connection = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
{
cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;
//TODO: Add Exception Handling
await connection.OpenAsync();
var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
var rowValues = new object[dataReader.FieldCount];
if (dataReader.Read())
{
dataReader.GetValues(rowValues);
for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
{
sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter),
rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
.AppendLine();
}
}
else
{
//No records found, do something here
}
dataReader.Close();
dataReader.Dispose();
}
return sb;
}
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.
I retrieve data from Oracle database and populate a gridview. Next, I try to run a query to select some data but I get an error.
Here is the code:
Db.cs:
public static OracleConnection GetConnection()
{
OracleConnection connection = null;
string connectionString = "Data Source=" + Database +
";User ID=" + UserID +
";Password=" + Password +
";Unicode=True";
try
{
connection = new OracleConnection(connectionString);
}
catch (OracleException ex)
{
throw ex;
}
return connection;
}
Parameters are sent from default.aspx.cs:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
main.aspx.cs retrieves all the data:
private OracleConnection connection = new OracleConnection();
private Select select = new Select();
protected void Page_Load(object sender, EventArgs e)
{
Response.Buffer = true;
if (Db.IsLoggedIn())
{
string selectCommand =
"SELECT " + Settings.TABLE + ".* FROM " + Settings.TABLE + " ORDER BY ";
foreach (string ob in Settings.OB) selectCommand += ob + ", ";
Session["Error"] = null;
connection = Db.GetConnection();
select = new Select(ddlBubID, ddlBusArea, ddlDrillSite, ddlWell, connection);
gvData.DataKeyNames = Settings.PK;
gvData.SelectedIndex = -1;
DS.ConnectionString = connection.ConnectionString;
DS.SelectCommand = selectCommand.Remove(selectCommand.Length - 2, 2);
DS.ProviderName = Settings.PROVIDER_NAME;
PopulateFooter(gvData.FooterRow);
}
else
{
Session["Error"] = Settings.ERROR_MESSAGE[0, 0];
Response.Clear();
Response.Redirect("default.aspx");
}
}
public string ToolTip(string column)
{
string value = "";
OracleCommand cmd = new OracleCommand();
cmd.Connection = connection;
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = " + column + ")";
cmd.CommandType = CommandType.Text;
OracleDataReader reader = cmd.ExecuteReader(); // I get an error here
reader.Read();
value = reader["COMMENTS"].ToString();
reader.Close();
return value;
}
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
for (int i = 1; i < e.Row.Cells.Count; i++)
{
try
{
LinkButton lb =
(LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
lb.ToolTip = ToolTip(lb.Text);
/* Blah Blah*/
}
catch { }
}
if (e.Row.RowType == DataControlRowType.Footer)
PopulateFooter(e.Row);
}
ToolTip(); throws an error:
Invalid operation. The connection is closed.
EDIT:
This would have been helpful:
Static Classes and Static Class Members
Might not be the problem but this looks weird:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
GetConnection is a static method and thus it does not see any member attributes you might be setting in the constructor (unless they are static as well). If they are all static, consider refactoring your code to use the singleton pattern as it is more readable.
Another thing is that the connection attribute is a member of the page class which is generated for each request (not per application). This means you need either create a new connection in ToolTip method (and any other method that accesses the database) or make the connection attribute static to make it per-application.
Try 2 things:
1.. For your ToolTip() method, the value column to compare for COLUMN_NAME will need to be wrapped properly with single quotes indicating a string/varchar literal value. Likely it's evaluating to COLUMN_NAME = foo when it should be COLUMN_NAME = 'foo'.
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = '" + column + "')";
2.. Try wrapping your ad-hoc SQL statements in BEGIN and END
3.. Consider refactoring your string building for your SELECT and dynamic ORDER BY clause. That you're doing it on the SelectCommand many lines below isn't obvious to the casual observer or maintainers later in its life.
string selectCommand = string.Format("SELECT {0}.* FROM {0} ORDER BY {1}"
,Settings.TABLE
,string.Join(",",Settings.OB));