I wrote this code in my login page. My code doesn't any error but update query doesn't apply on my database.
Fist query works and I redirect to index.aspx but update query (second query) doesn't apply!!!!
protected void btnLogin_Click(object sender, EventArgs e)
{
Database db1 = new Database();
string query = "select * from Admins where UserName=#username and cast(Password as varbinary)=cast(#password as varbinary)";
SqlCommand smd = new SqlCommand(query, db1.sc);
smd.Parameters.AddWithValue("#username", txtUsername.Text);
smd.Parameters.AddWithValue("#password", General.CreatePasswordHash(txtPassword.Text));
SqlDataReader sdr = smd.ExecuteReader();
smd.Parameters.Clear();
if (sdr.Read())
{
Session.Add("username", sdr[0].ToString());
string nowEnter = sdr[5].ToString();
query = "update Admins set LastEnter=#lastEnter, NowEnter=#nowEnter where UserName=#username";
string now = General.getPersianDateNow() + " ساعت " + General.getPersianTimeNow();
smd.CommandText = query;
smd.Parameters.AddWithValue("#lastEnter", nowEnter);
smd.Parameters.AddWithValue("#nowEnter", now);
smd.Parameters.AddWithValue("#username", sdr[1].ToString());
sdr.Close();
smd.ExecuteNonQuery();
Response.Redirect("~/admin/Index.aspx", false);
}
else
{
lblError.Visible = true;
}
}
In my opinion the problem is with index of sdr. First one you invoke
Session.Add("username", sdr[0].ToString());
Two lines below you use
smd.Parameters.AddWithValue("#username", sdr[1].ToString());
Anyway the safest way is to create select statement with named colums instead of using *
Check that the value you are using for the username exists in the table.
You're also adding the same parameter twice. I don't know how the SqlCommand class will handle that and I can't test it right now, but I think it might be a good idea to clear your parameters (smd.Parameters.Clear()) between executions.
Related
In my website made by asp.net, we can update the email address, password, place and about myself of a user given the old password is correct. Now what I do is, login, then use this code to update:
protected void update_profile(object sender, EventArgs e)
{
string constr = ConfigurationManager.ConnectionStrings["Khulna_website"].ConnectionString;
using (SqlConnection connection = new SqlConnection(constr))
{
string user_email = (string)(Session["User"]);
string pass = encrypt_pass(old_password.Text);
if (pass != (string)(Session["Password"]))
{
pass_err_message.Text = "Wrong password";
pass = (string)Session["Password"];
}
else
{
pass = encrypt_pass(new_password.Text);
}
string insertQuery = "update dbo.users set user_password=#new_password, user_place = #new_place, user_about=#new_about where user_email =" +user_email;
SqlCommand com = new SqlCommand(insertQuery, connection);
connection.Open();
com.Parameters.AddWithValue("#new_password", pass);
com.Parameters.AddWithValue("#new_about", new_about.Text);
com.Parameters.AddWithValue("#new_place", new_place.Text);
try
{
com.ExecuteNonQuery();
upload_err_message.Text = "Successfully uploaded";
connection.Close();
}
catch (Exception ex)
{
profile_settings_err_message.Text = "Update error: " + ex.Message;
}
}
}
But when I try to update it is saying: Update error: The multi-part identifier "abcde#gmail.com" could not be bound. And my session is gone! I thought maybe it was due to foreign key, so I removed all the foreign keys of the database, but it is still happening. What's wrong here?
EDIT: I have added back the foreign keys, since I need them to on delete cascade. I just deleted them to see if it works.
I am just taking a guess, but I believe your issue will be found right here:
"... user_email =" +user_email;
Try doing something like
"... user_email = #email";
com.Parameters.AddWithValue("#email", user_email);
That's the better way... however if you want to get lackadaisical you should be able to just surround the email in single quotes.
"... user_email = '" + user_email + "'";
I hope this helps!
Okay I am a noob to parameterized queries. I understand why you should use them and all but I cannot find any resource that shows the correct way or at least one that shows the correct way that actually works.
So my question is about whether or not my code is right. It compiles and runs just fine but it returns absolutely nothing in the gridview.
protected void SearchButton_Click(object sender, EventArgs e)
{
string searchBoxValue = SearchBox.Text;
string columnNameValue = ColumnName.SelectedValue;
columnNameValue.ToLower();
SqlCommand searchCommand = new SqlCommand();
searchCommand.Connection = connection;
searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where #columnname = #searchterm";
SqlParameter columnParam = new SqlParameter();
columnParam.ParameterName = "#columnname";
columnParam.Value = columnNameValue;
SqlParameter searchBoxParam = new SqlParameter();
searchBoxParam.ParameterName = "#searchterm";
searchBoxParam.Value = searchBoxValue;
searchCommand.Parameters.Add(columnParam);
searchCommand.Parameters.Add(searchBoxParam);
UpdateTable(searchCommand);
}
The UpdateTable function takes in the an SqlCommand object and then uses a DataAdapter object to execute the command and fills a DataTable object then sets the gridview datasource to the datatable object and binds it.
Like I said before I am really looking for the proper way to do this? do I need a stored procedure in order to do this? I am confused by all this and why it is not working.
You cannot parameterise #columnname. This needs to be a literal in your query.
Your statement
select
/* .... */
from registrants where #columnname = #searchterm
will return all rows from registrants if the value of the parameters happens to be the same or no rows otherwise.
It will not look and see if you have a column of that name and see if #searchterm exists in it.
To do this in a safe way you would need to check that columnNameValue matches one of a whitelist of valid column names (as you must know the possible column names in that table) and concatenate it into your query. Do not concatenate unvalidated user input. as then you open yourself up to SQL injection.
So you might implement it something like
using System.Linq;
protected void SearchButton_Click(object sender, EventArgs e)
{
string columnNameValue = ColumnName.SelectedValue.ToLower();
var validColumnNames = new string[] { "firstname", "lastname", "zipcode" };
if (!validColumnNames.Contains(columnNameValue))
{
throw new Exception("Unexpected column name " + columnNameValue);
}
/* ... code omitted */
searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where " + columnNameValue + " = #searchterm";
/* ... code omitted */
}
The purpose of paramtrized command are to prevent sql injection. You cannot parametrize the name of the column, sql will take it as a string.
protected void SearchButton_Click(object sender, EventArgs e)
{
string searchBoxValue = SearchBox.Text;
string columnNameValue = ColumnName.SelectedValue;
columnNameValue.ToLower();
SqlCommand searchCommand = new SqlCommand();
searchCommand.Connection = connection;
//Put the column name directly in the request, but use a parameter for the search value
searchCommand.CommandText = "select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where " + columnNameValue + " = #searchterm";
/* No need for this part
SqlParameter columnParam = new SqlParameter();
columnParam.ParameterName = "#columnname";
columnParam.Value = columnNameValue;
*/
SqlParameter searchBoxParam = new SqlParameter();
searchBoxParam.ParameterName = "#searchterm";
searchBoxParam.Value = searchBoxValue;
//searchCommand.Parameters.Add(columnParam);
searchCommand.Parameters.Add(searchBoxParam);
UpdateTable(searchCommand);
}
Your issue is in how you're trying to make your column name as a parameter. You'll want to change the query as a whole to reflect which column you want to filter by. Try the following:
protected void SearchButton_Click(object sender, EventArgs e)
{
string searchBoxValue = SearchBox.Text;
string columnNameValue = ColumnName.SelectedValue;
columnNameValue.ToLower();
SqlCommand searchCommand = new SqlCommand();
searchCommand.Connection = connection;
searchCommand.CommandText = String.Format("select firstname AS FirstName,lastname AS LastName, zipcode as ZipCode, phone AS Phone, email AS Email, cancersurvivor AS CancerSurvivor, ethnicity AS Ethnicity from registrants where {0} = #searchterm",columnNameValue);
SqlParameter searchBoxParam = new SqlParameter();
searchBoxParam.ParameterName = "#searchterm";
searchBoxParam.Value = searchBoxValue;
searchCommand.Parameters.Add(columnParam);
searchCommand.Parameters.Add(searchBoxParam);
UpdateTable(searchCommand);
}
If you want this to work, you'd have to build the SQL statment dynamically and execute with sp_executesql inside the proc as so:
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET #SQLString =
N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #BusinessEntityID';
SET #ParmDefinition = N'#BusinessEntityID tinyint';
/* Execute the string with the first parameter value. */
SET #IntVariable = 197;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
/* Execute the same string with the second parameter value. */
SET #IntVariable = 109;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
You still have the benefit of using parametrized queries and not exposing yourself to SQL Injection.
Source here.
Another very useful link is this.
I'm using Asp.net c# and MYSql as back-end. I'm updating a table,but table is not updating.There are only 3 columns in the table.
There is no exception when I'm executing the command object. But this returns 0 value from cmd.ExecuteNonQuery().
I debugged this and found cmd.Parameters are full with values. and if i manually run the update command in mysql it works fine.
the table is as follow
column -- Datatype
ShortText -- varchar
title -- varchar
id -- int
Please guide me...
int retVal = 0;
string shortText = ((TextBox)fmvwShortText.FindControl("txtShortText")).Text.Trim();
try
{
int id = Convert.ToInt32(((Label)fmvwShortText.FindControl("lblShrtTextID")).Text);
MySqlConnection con = new MySqlConnection(System.Configuration.ConfigurationManager.AppSettings["conn"]);
cmd = new MySqlCommand();
cmd.Connection = con;
cmd.CommandText = "UPDATE temp_posts SET ShortText=#shrtText WHERE id=#id AND Title=#title";
cmd.Parameters.Add("#shrtText", MySqlDbType.VarChar).Value = shortText;
cmd.Parameters.Add("#title", MySqlDbType.VarChar).Value =Session["EditTitle"].ToString();
cmd.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
con.Open();
retVal = cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception e) { }
return retVal;
Is it possibly a casing issue with your Title parameter? I notice you are only updating if the ID & Title match exactly?
Also as a general rule of thumb, when using objects which implement IDisposable you should wrap them with a using statement, this will make sure your objects are always disposed (even on the result of an error)
using (var con = new MySqlConnection(...))
{
using (var cmd = new MySqlCommand(...))
{
....
}
}
First of all thank you every one who kept looking and tried their best to sort out this problem with me..
Finally got the solution.
In my code I used # in cmd.CommandText and in parameters.
But when I replace this # with ? both in cmd.CommandText and in parameters and used the cmd.ExecuteScalar(); this worked.
Actually Parameter names depend on the provider. When using the provider for
SQL Server, it should start with # (e.g. #param1). For Oracle
provider, it should start with a colon (...for e.g. aram1. For
OleDb provider, just a question mark (?) would work
Thank you everyone to contribute your best... many thanks
But i'm still left with a question that ExecuteScalar() is updating the records in the database? I am with no answer... looking for this.
Try this nt sure about code formating coz currently am not using ide frmwrk
int retVal = 0;
string shortText = ((TextBox)fmvwShortText.FindControl("txtShortText")).Text.Trim();
try
{
int id = Convert.ToInt32(((Label)fmvwShortText.FindControl("lblShrtTextID")).Text);
MySqlConnection con = new MySqlConnection(System.Configuration.ConfigurationManager.AppSettings["conn"]);
cmd = new MySqlCommand("UPDATE temp_posts SET ShortText='"+shortText+"' WHERE id='"+id+"' AND Title='"+Session["EditTitle"].ToString()+"'",con);
con.Open();
retVal = cmd.ExecuteNonQuery();
con.Close();
return retVal;
}
catch (Exception e) { }
I am building a Forum in ASP.Net but have a small problem.
I have 1 user who creates a topic and can write a post to it fine, but if another user logs in, it won't insert the post into the database. It's returning that it does but nothing inserts. The original user can login and still post but no-one else can.
this is my code in behind
protected void addPostBtn_Click(object sender, EventArgs e)
{
//Define ADO.NET objects.
string insertSQL;
string topic = Request.QueryString["topicid"].ToString();
insertSQL = "INSERT INTO Posts (TopicID, PostBody, PUserID)"
+ "VALUES (#Topic, #NewPostText, #PUserID)";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
// Try to open the database and execute the update
int added = 0;
try
{
cmd.Parameters.AddWithValue("#Topic", topic);
cmd.Parameters.AddWithValue("#NewPostText", newPostText.InnerText);
cmd.Parameters.AddWithValue("#PUserID", Session["User_ID"]);
con.Open();
added = cmd.ExecuteNonQuery();
lblResults.Text = "Your post has been added";
}
catch (Exception err)
{
lblResults.Text = "Error inserting record. " + err.Message;
}
finally
{
con.Close();
}
if (added > 0)
{
this.BindRepeater();
}
}
I don't get any errors at all. It says it submitted fine, but it's not in the database unless the original poster does it.
EDIT:
Just realized it's to do with my view. This is my current view that it's reading from
SELECT dbo.Posts.PostBody, dbo.Posts.PostDate, dbo.Posts.PostID, dbo.[User].username, dbo.Topic.TopicID
FROM dbo.Topic RIGHT OUTER JOIN
dbo.Posts ON dbo.Topic.TopicID = dbo.Posts.TopicID LEFT OUTER JOIN
dbo.[User] ON dbo.Topic.TUserID = dbo.[User].UserID AND dbo.Posts.PUserID = dbo.[User].UserID
But it's returning NULL now for the other users names
The view needs to be as follows
SELECT dbo.Posts.PostBody, dbo.Posts.PostDate, dbo.Posts.PostID, dbo.[User].username, dbo.Topic.TopicID
FROM dbo.Topic LEFT OUTER JOIN
dbo.Posts ON dbo.Topic.TopicID = dbo.Posts.TopicID LEFT OUTER JOIN
dbo.[User] ON dbo.Posts.PUserID = dbo.[User].UserID
My registration form has got a CreateUserWizard. I used its event that is fired after the user is created.
Then I obtain the users identity and key. In the last line, I send the unique key to a function inside a class that should insert the key into the Users table (the field is a primary key and is unique).
public partial class Registration : System.Web.UI.Page
{
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
MembershipUser CurrentUser = Membership.GetUser(User.Identity.Name);
int i =(int) CurrentUser.ProviderUserKey;
RegisterAdo.InsertUsers(i);
}
}
Below, I execute the query with the value that I passed and insert the user into a database
class RegisterAdo
{
public static void InsertUsers(int UsersIDentity)
{
string myConnectionString = WebConfigurationManager.ConnectionStrings["YourGuruDB"].ConnectionString;
SqlConnection sqlConnect = new SqlConnection(myConnectionString);
SqlCommand sqlCommand = new SqlCommand(RegisterAdo.insertCommand(UsersIDentity), sqlConnect);
try
{
sqlConnect.Open();
sqlCommand.ExecuteNonQuery();
}
catch (Exception x)
{
}
finally
{
sqlConnect.Close();
}
}
public static String insertCommand(int UsersIdentityToinsert)
{
string insertCommand="INSERT INTO Users(";
insertCommand += "UserID)";
insertCommand += "VALUES('";
insertCommand += UsersIdentityToinsert+"')";
return insertCommand;
}
My question is whether it is the best way to insert UserID into a table, and whether I do it right at all. I need the UserID to be unique, and the whole command executed with no fail...(just after the user was created and the whole UserCreateUser finished validating the user!!!
I would change two things mainly:
don't concatenate together your SQL statement - this opens doors to SQL injection attacks. Use parametrized queries instead - they are both safer, and they perform better (since only a single copy of the query's execution plan needs to be created and cached and will be reused over and over again)
put your SqlConnection and SqlCommand objects into using blocks so that they'll be automatically freed / disposed when the using blocks ends (and you can save yourself the finally block of the try...catch construct, too!).
So my code would look like this
public static void InsertUsers(int UsersIDentity)
{
string myConnectionString = WebConfigurationManager.ConnectionStrings["YourGuruDB"].ConnectionString;
string insertStmt =
"INSERT INTO dbo.Users(UserID) VALUES(#UserID)";
using(SqlConnection _con = new SqlConnection(myConnectionString))
using(SqlCommand _cmd = new SqlCommand(insertStmt, sqlConnect))
{
_cmd.Parameters.Add("#UserID", SqlDbType.Int).Value = UsersIDentity;
try
{
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
catch (Exception x)
{
// do something if error occurs
}
}