Sql error in asp.net c# - c#

If you please help me out i have an error in my code that i can not understand it.
the error is:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Incorrect syntax near 'Login'.
and my code:
public static void ChangePassword(string login, string password)
{
var sqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
string query = #"update Organizer set Password ="+ password + "where Login=" + login + "";
SqlCommand cmd = new SqlCommand(query, sqlCon);
cmd.CommandType = CommandType.Text;
try
{
sqlCon.Open();
cmd.ExecuteNonQuery();
sqlCon.Close();
}
catch (Exception ee) { throw ee; }
}

We've seen enough sql injection attacks, we don't need another one, please fix your code and use parameters.
Use using blocks to avoid leaking connections.
Install an exception handler like ELMAH.
Don't save passwords in the database
using (var sqlCon = new SqlConnection(...))
{
string query = #"update Organizer set Password =#password where Login=#login";
SqlCommand cmd = new SqlCommand(query, sqlCon);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#password", SqlDbType.VarChar, 8000);
cmd.Parameters["#password"].Value = password;
cmd.Parameters.Add("#login", SqlDbType.VarChar, 8000);
cmd.Parameters["#login"].Value = login;
sqlCon.Open();
cmd.ExecuteNonQuery();
sqlCon.Close();
}

Try
string query = #"update Organizer set Password ='"+ password + "' where Login= '" + login + "'";
You are missing the ' around string, that being said you are likely very open to sql injection attacks ( Im guessing because of the code, and lack of a clearing function).
Also make sure your not storing passwords in plain text :)
The ' is used like " in sql.

If you were going to use the code above, your issue is that you're not wrapping the new password or login in single quotes:
string query =
#"update Organizer set Password = '" +
password +
"' where Login= '" + login + "'";
But I wouldn't use that code at all. It's quite dangerous since it allows people to pass in arbitrary SQL. I would use parameterized queries instead:
var query = "update organizer set password = #password where login = #login";
var command = new SqlCommand(query, sqlCon);
command.Parameters.Add("#password", SqlDbType.VarChar, 100, password);
command.Parameters.Add("#login", SqlDbType.VarChar, 100, login);

You need single quotes...
set Password = ' /*<---*/ "+ password + "' /*<---*/ where Login=' /*<---*/ " + login + "' /*<---*/ "

Related

C# Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll

Apologies in advance if I missed an answer to this somewhere but I wasn't quite finding it anywhere. So I'm building an application that scans PDF's of service orders our company gets, parses it, and inserts it into a SQL DB. The problem is at the end of this code. It successfully :
saves the original pdf in the proper folder
scans the pdf and parses it
inserts the correct data into the service order table
grabs PK of service order just created as we need that for the next batch of inserts
Here is where it gets hung up with a Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll
I foreach through all the instruments as there are multiples per Service Order, but it is erroring on this somewhere. to be clear I put a break point on the insert statement and all of the data is good and in the proper format ("string" int)
I feel like its in my connection maybe?
Anyways, thanks in advance for the help.
string filename = Path.GetFileName(FileUpload1.FileName);
FileUpload1.SaveAs(Server.MapPath("~/PDF/") + filename);
// Now we parse the PDF by creating a new ServiceOrder object and parsing from it.
ServiceOrder so = new ServiceOrder();
// Make sure we load the PDF from the correct path on the server
so.LoadPDF(Server.MapPath("~/PDF/") + filename);
String strConnString = "Data Source=127.0.0.0;Initial Catalog=SOMECATALOG;User ID=SOMEUSER;Password=SOMEPASSWORD";
// Insert Into Service Orders Table
string defaultdate = DateTime.Now.ToString("yyyy-MM-dd");
String strQuery = "insert into TServiceOrders (strServiceOrderNo, intStatusCodeID, strCustomerName, strCustomerNo, strCustomerAddress1, strCustomerAddress2, strCustomerAddress3, intRepID, strServiceDescription, strServiceRequestDate, strServiceOrderDate, strNotes) values ('"
+ so.ServiceOrderNumber.ToString() + "', 2, '"
+ so.CustomerContactName.ToString() + "', '"
+ so.CustomerNumber.ToString() + "', '"
+ so.CustomerContactAddress1.ToString() + "', '"
+ so.CustomerContactAddress2.ToString() + "', '"
+ so.CustomerContactAddress3.ToString() + "', 1, '', '"
+ defaultdate + "', '" + defaultdate + "', '')";
SqlConnection conn = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand(strQuery, conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
// Grabbing latest primary key od service order just added for next instrument inserts
int lastid = 999999;
String strPKquery = "select top 1 intServiceOrderID from TServiceOrders order by intServiceOrderID desc";
SqlDataReader rdr = null;
SqlConnection conn2 = new SqlConnection(strConnString);
SqlCommand cmd2 = new SqlCommand(strPKquery, conn2);
try
{
conn2.Open();
rdr = cmd2.ExecuteReader();
while (rdr.Read())
{
lastid = (int)rdr["intServiceOrderID"];
}
}
finally
{
if (rdr != null)
{
rdr.Close();
}
if (conn2 != null)
{
conn2.Close();
}
}
// Insert Into Service Instruments Tables
SqlConnection conn3 = new SqlConnection(strConnString);
conn3.Open();
foreach (ServiceInstrument sin in so.ServiceInstruments)
{
string sim = "";
sim = sin.ServiceInstrumentModel;
if (String.IsNullOrEmpty(sim))
{
sim = "";
}
else
{
sim = sin.ServiceInstrumentModel.ToString();
}
string sid = "";
sid = sin.ServiceInstrumentDescription;
if (String.IsNullOrEmpty(sid))
{
sid = "";
}
else
{
sid = sin.ServiceInstrumentDescription.ToString();
}
string sis = "";
sis = sin.ServiceInstrumentSerial;
if (String.IsNullOrEmpty(sis))
{
sis = "";
}
else
{
sis = sin.ServiceInstrumentSerial.ToString();
}
string sih = "";
sih = sin.ServiceInstrumentHandle;
if (String.IsNullOrEmpty(sih))
{
sih = "";
}
else
{
sih = sin.ServiceInstrumentHandle.ToString();
}
string sip = "";
sip = sin.ServiceInstrumentParentAsset;
if (String.IsNullOrEmpty(sip))
{
sip = "";
}
else
{
sip = sin.ServiceInstrumentParentAsset.ToString();
}
String strQuery3 = "insert into TServiceInstruments values ('" + sim.ToString() + "', '" + sid.ToString() + "', '" + sis.ToString() + "', '" + sih.ToString() + "', " + sip.ToString() + ", " + lastid + ")";
SqlCommand cmd3 = new SqlCommand(strQuery3, conn3);
cmd3.ExecuteNonQuery();
}
conn3.Close();
When writing insert statements you should always specify the column names. This will protect the code from changes in the order of the columns in the table schema.
You are not using parameters in your sql statements, this leaves your code vulnerable to Sql Injection.
You should use using statements around your SqlConnection instances to ensure they are closed even when an Exception occurs.
Your logic is very difficult to follow, split your code until methods with meaningful names instead of having 1 "God" method that does everything.
If you follow those guidelines the problem will most likely solve itself in your refactoring.
Update Code Fragment
Note that you should always specify the correct types for your columns and the length if applicable. Also pass the actual value and never the string value.
const String strQuery3 = "INSERT INTO TServiceInstruments (sim, sid, sis, sih, sip, lid) VALUES (#sim, #sid, #sis, #sih, #sip, #lid)";
using(var conection = new SqlConnection(strConnString))
using(SqlCommand command = new SqlCommand(strQuery3, connection))
{
command.Parameters.Add(new SqlParameter("#sim", SqlDbType.VarChar, 200){Value = sim});
command.Parameters.Add(new SqlParameter("#sid", SqlDbType.VarChar, 200){Value = sid});
command.Parameters.Add(new SqlParameter("#sis", SqlDbType.VarChar, 200){Value = sis});
command.Parameters.Add(new SqlParameter("#sih", SqlDbType.VarChar, 200){Value = sih});
command.Parameters.Add(new SqlParameter("#sip", SqlDbType.Int){Value = sip});
command.Parameters.Add(new SqlParameter("#lid", SqlDbType.Int){Value = lid});
connection.Open();
command.ExecuteNonQuery();
}
Final note: You really need to learn how to read Exceptions and this includes the Stack Trace which points directly to the line in the call stack where the Exception originated. If you can understand this then debugging becomes much easier.
Maybe this doesn't deserve to be an answer, but I'm trying to build some reputation, so here goes :).
I suspect that your error lies in the "insert into TServiceInstruments ..." statement. Namely, you are giving the table more (or less) columns. As a good practice, always specify the columns, like this:
insert into TServiceInstruments (column1, column2, column3)
values (1, 2, 3)

C# Passing parameters to stored procedure with EXEC query

I am trying to pass parameters from my program to Stored Procedure in EXEC format.Following is my code
public void button1_Click(object sender, EventArgs e)
{
frm = new FrmLogin();
OleDbConnection conn = new OleDbConnection("File Name=E:\\Vivek\\License Manager\\License Manager\\login.udl");
try
{
conn.Open();
string user = username.Text;
string pass = password.Text;
string query = "EXEC dbo.checkuser"' + username.Text'" + " " + "'password.Text'"";
OleDbCommand cmd = new OleDbCommand(query,conn);
cmd.ExecuteNonQuery();
// Retrieve the return value
string result = query.ToString();
MessageBox.Show(result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
conn.Close();
}
What should I write in string query=" "?,I am trying to pass username and password as parameters to the stored procedure and once the query executes and returns the result ,I will store it in another variable named result.Am I doing it the right way? I am new to C#
Please suggest,
Thanks
Building command text with dynamically inserted segments from user input is very dangerous, and leaves you open to SQL Injection.
Below is a slight variation which parameterizes those strings. This approach is much safer.
string query = "dbo.checkuser";
OleDbCommand cmd = new OleDbCommand(query,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#username", username.Text);
cmd.Parameters.AddWithValue("#password", password.Text);
Note: This updated version sets up the command as a stored procedure, instead of plain text.
try this
OleDbCommand cmd = new OleDbCommand("StoredPorcedureName",conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameter.AddWithValue("#user", username.Text);
cmd.Parameter.AddWithValue("#pwd", password.Text);
cmd.ExecuteNonQuery();
That looks Okay at a glance except for your query string. Change to:
string query = "EXEC dbo.checkuser '" + username.Text "', '" + password.Text + "'";
might work better.
Edit
Yes, as per comments about SQL injection, Troy's answer is significantly better.
Just for completeness that can be possibly used in other situations, you can avoid SQL injection using this method by trying something like:
string query = "EXEC dbo.checkuser '" + username.Text.Replace("'", "''") "', '" + password.Text.Replace("'", "''") + "'";

Database insert error: "string or binary data would be truncated"

When I log in, I am storing my username in the session. My requirement is that I want to store my username in my database. Here I am storing it in username1. When the username is entered, I can print it using response.write() and it is printing perfectly. However, when I am storing it in the database it is producing this error:
**sqlException was unhandled by user code
and exception at cmd.ExecuteScalar();
String or binary data would be truncated.
The statement has been terminated.**
Following is my ado.net code:
using (SqlConnection con =
new SqlConnection("Data Source=.;database=testdb1;Integrated Security=SSPI")) {
con.Open();
// SqlCommand cmd = new SqlCommand("delete from fileinfo where ID=" + Convert.ToInt32(Request.Params["one"]), con);
string uname = (string) Session["fname"].ToString() + " " + Session["lname"].ToString(); //Session["fname"].ToString()+" "+Session["lname"].ToString();
// Response.Write(uname);
// uname = "sri hari";
uname = uname + " ";
string uname1 = uname;
uname = uname.Trim();
SqlCommand cmd = new SqlCommand("insert into qry_details values('" + txt_query_name.Text + "','pending for approval','" + txt_query_description.Text + "','" + DateTime.Now.ToString("yyyy-MM-dd") + "','" + qry + "','" + uname1 + "')", con);
cmd.ExecuteScalar();
}
check the length of qry_details table and see if its smaller than the string you send to the db?
basically the exception says you are trying to something bigger than the column length.
I would recommend you using a parametrized query. Your code is now vulnerable to SQL injection. Also you should use the ExecuteNonQuery method on the SQL command instead of ExecuteScalar when inserting values to the database:
var connectionString = "Data Source=.;database=testdb1;Integrated Security=SSPI";
using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = "INSERT INTO qry_details VALUES (#query_name, 'pending for approval', #query_description, #date, #qry, #username)";
cmd.Parameters.AddWithValue("#query_name", txt_query_name.Text);
cmd.Parameters.AddWithValue("#query_description", txt_query_description.Text);
cmd.Parameters.AddWithValue("#date", DateTime.Now);
cmd.Parameters.AddWithValue("#qry", qry);
cmd.Parameters.AddWithValue("#username", uname1);
cmd.ExecuteNonQuery();
}
This error mostly happen when the inserting value is larger than the field width defined in table on SQL Server.
Check if you are inserting date and time using DateTime.Now c# fuction, your Table must be of type DateTime. not Date or Time only.

Login page - Checking the database

I am trying to make a simple login page, user enters ID and password, and chooses role from a dropdown list:Student, Administrator or Instructor. Here is the code:
protected void loginButton_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection();
con.ConnectionString = "Data Source=.\\SQLEXPRESS;Initial Catalog=University;Integrated Security=True;Pooling=False";
//myConn.Open();
//string strqry = "Insert into students values (" + TextBox1.Text +
//",'" + TextBox2.Text + "','" + TextBox3.Text + "')";
//SqlCommand myCom = new SqlCommand(strqry, myConn);
//int numrow = myCom.ExecuteNonQuery();
//myConn.Close();
Int32 verify;
string query1 = "Select count(*) from Login where ID='" + idBox.Text + "' and Password='" + passwordBox.Text + "' and Type='"+ LoginAs.Text +"'" ;
SqlCommand cmd1 = new SqlCommand(query1, con);
con.Open();
verify = Convert.ToInt32(cmd1.ExecuteScalar());
con.Close();
if (verify > 0)
{
Response.Redirect("succesful.aspx");
}
else
{
Response.Redirect("unsuccesful.aspx",true);
}
}
The problem is, when i try without checking the value of the dropdown list called "LoginAs", it works fine and makes validation. But when i also check the Type, which is either Student, Administrator or Instructor it always makes unsuccesful login even though all the information is correct. Can anyone help me to find what is wrong?
Thanks
use parametrized queries maybe it will be resolved and you would prevent risks it goes like this
cmd1.Parameters.AddWithValue("#ID", idBox.Text);
The first points to check is the:
The all of the letters should has the same case.
The role should be truncated in database and in the application
But, it's preffered to use enum/int to define role of user instead of a text name.
Give a try to SqlDataReader class. You can catch if an reads occur.
Here is the link. While this not the case I recommend you to use a scalar function in your database or use EntityFramework or other ORM tools.

Comparing two rows in the same table in sql server

I have looked at similar answers but, this is what I am looking for since I did not find any answers from previously answered questions:
This is my scenario: I have a table [res_user] with username, password, key_pin which saves a username, an encrypted password, and a 4 digit pin or key.
I am making an app in C# that allows a manager to log in and make changes to the database from the app itself.
The manager is first prompted to log in with a username, a password, and their key_pin they are provided with. The pin is what will encrypt and decrypt the password to and from the database.
Now I have a username [manager] and an encrypted password already saved in the database with the key_pin.
How can I make sure that the manager logging in is the right one, meaning how can I compare the username and the encrypted password in the database from the C# app.
These are the steps that I though of that I will implement in the app itself (using SQL syntax in c#):
Encrypt the password,
Get the saved encryption in the database using the login username, and
Compare the encryption returning a yes or a no back to the app for access control.
allowing 5 attempts to log in.
This is the first and second part I did:
try
{
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["STRING"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("dbo.Res_User", con))
{
cmd.CommandText = "INSERT INTO Res_User(username, password, key_pin) SELECT '" + username + "' , dbo.fnEncDecRc4('" + pin + "','" + password + "'), '" + pin + "'";
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Added", "Information", MessageBoxButtons.OK);
cmd.CommandText = "SELECT password FROM Res_User WHERE username = #username";
cmd.Parameters.AddWithValue("#username", username);
cmd.ExecuteNonQuery();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
MessageBox.Show(reader["password"].ToString(), "Information", MessageBoxButtons.OK);
}
}
}
How do I go about doing the third part?
Only if someone can help me compare the saved enc. password and the login enc. password which I did in part one.
Let me know if more information is needed.
Thank You.
Any help will be appreciated.
You could try re-encrypting the password and pin on the server when you're doing validation on the server. So that you will call your encrypt function, then do a comparison and if you have results, you know that the correct password was entered. Modifying your code, it would look like:
try
{
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["STRING"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("dbo.Res_User", con))
{
cmd.CommandText = "INSERT INTO Res_User(username, password, key_pin) SELECT '" + username + "' , dbo.fnEncDecRc4('" + pin + "','" + password + "'), '" + pin + "'";
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Added", "Information", MessageBoxButtons.OK);
cmd.CommandText = "SELECT password FROM Res_User WHERE username = #username AND key_pin = #pin AND password = dbo.fnEncDecRc4(#pin, #password)";
cmd.Parameters.AddWithValue("#username", username);
cmd.Parameters.AddWithValue("#pin", pin);
cmd.Parameters.AddWithValue("#password", password);
cmd.ExecuteNonQuery();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
//successfully validated.
}
}

Categories

Resources