I have an ASP.NET wizard where a user fills in their personal details and the values of the text boxes are inserted into a MS SQL record.
However, when inserting the record, I get the following error:
SQL Server error #241: Conversion failed when converting date and/or
time from character string
Code:
string insertSQL;
insertSQL = "INSERT INTO member (";
insertSQL += "UserId, mem_dob,) ";
insertSQL += "VALUES (";
insertSQL += "#UserId, #mem_dob";
insertSQL += ")";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
//Add the parameters.
cmd.Parameters.AddWithValue("#UserId", providerIdKeyString);
cmd.Parameters.AddWithValue("#mem_dob", DateOfBirth.Text);
Any ideas the best way to fix? Should I not be using a text box but something else?
I wanted to keep the web form simple - it validates the dates OK so thought the date should be valid.
Thanks
You should simply parse the Text to a valid DateTime.
cmd.Parameters.AddWithValue("#mem_dob", DateTime.Parse(DateOfBirth.Text));
http://msdn.microsoft.com/en-us/library/1k1skd40%28v=VS.100%29.aspx
Of course you should have already validated that the entered "date" is valid at this stage.
Sounds like the date entered in your Text Box is an invalid date according to SQL. Before attempting to add the date as a parameter, first check it's validity. e.g.
DateTime myDate;
if(textBox1.TryParse(DateOfBirth.Text, out myDate))
{
// Date is valid.
} else
{
// Take corrective actions to fix the date.
}
Simply attempting to parse the date without knowing whether it's valid or not will leave your application open to a failure, as you simply shouldn't trust the user to enter a valid date.
DateTime t;
String Date = String.Empty;
if (DateTime.TryParse(Date, out t))
{
cmd.Parameters.AddWithValue("#mem_dob", t);
}
You should have to create simple user-control that contains three dropdown controls - for day, month and year and a public property/method to set/get date. You may think about ASP.NET Ajax controls.
In case if you want to use Textbox then restrict the user input via CompareValidator control or some sort of JavaScript and regular expression.
To parse date string use DateTime.TryParse, or DateTime.ParseExact (DateTime.TryParseExact) method.
string[] inputFormat = {"dd-MM-yy","dd/mm/yy","dd-MMM-yyyy"};
string userDate = "31-12-11";
DateTime date;
if (DateTime.TryParseExact(userDate,
inputFormat,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date))
{
//valid
}
Related
I need to update a row where there exists a certain value. The ExecuteNonQuery returns a 0 meaning the database is not being updated. When stepping through in debug, the update is hit and contains the correct values, however no updates are being done.
string verifySql = #"UPDATE UserInfo SET Verified='#Verified'
WHERE UserID='#UserID'";
using (var con = newSqlConnection(
ConfigurationManager.ConnectionStrings["UserInfoDB"].ConnectionString))
using (var cmd = new SqlCommand(verifySql, con))
{
con.Open();
cmd.Parameters.AddWithValue("#Verified", "Verified " + DateTime.Now);
cmd.Parameters.AddWithValue("#UserID", user.UserId);
Response.Write(cmd.ExecuteNonQuery());
con.Close();
}
Lose the single quotes around the parameter names in your sql statement. You don't need them, and they're making your code interpret your parameter placesholders as simple string literals.
Then remove the con.Close() line. You don't need that either; it's covered by the using block.
Finally, you might also consider changing your verified column to a simple DateTime type, rather than trying to store that data as text.
I have the following code snippet.
SqlCommand cmd = new SqlCommand("SELECT FName,LName FROM EMPLOYEE_TABLE WHERE EmployeeID = '" +TextBox1.Text + "' AND Password = '"+ TextBox2.Text +"'", con);
SqlDataReader x = cmd.ExecuteReader();
try
{
if (x.Read())
{
name = (string)x["FName"] +' '+ (string)x["LName"];
Session["NAME"] = name;
Session["ID"] = TextBox1.Text;
Response.Redirect("sample.aspx?action=On_Click");
}
else
{
errormsg.Text = "login failed.Please enter Valid UserID and Password";
errormsg.ForeColor = System.Drawing.Color.Red;
}
}
catch (Exception exp)
{
errormsg.Text = "Sorry,You dont have access to this portal.";
}
finally
{
x.Close();
con.Close();
}
Now, when i use a valid id (that exists) and password as abc' or 'x'='x then it logs in into the first account of the table in the database. Till this it's fine.
However when I try to debug the code, it throws an error Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack..
Also if it is throwing an error then why is it logging into this 1st account of the database. Note: the first account of the database has a different userid than that which i m providing.
Note: I am the developed of this application. So I'm not doing anything illegal. :)
Look at this part of your SQL:
"' AND Password = '"+ TextBox2.Text +"'"
With your password, it's
"' AND Password = ''x'='x'"
which is not the SQL you want.
Even if you are trying to do SQL injection, you have to result in valid SQL. Usually, it's by ending the statement with a semi-colon after closing the quote. See this:
http://xkcd.com/327/
OK, to provide an answer based on the primary issue you've got (as you've stated, you're new to the SQL Injection issue).
SQL Injection is caused by dynamically building a SQL query using user input as part of the construction. The simplest solution to this in .Net is to create a parameterized query.
I think Jeff Atwood has the most complete yet concise article providing an explanation and complete example here
Quoted from above link:
SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s = "SELECT email, passwd, login_id, full_name " +
"FROM members WHERE email = #email";
SqlCommand cmd = new SqlCommand(s);
cmd.Parameters.Add("#email", email);
SqlDataReader reader = cmd.ExecuteReader();
The issue at hand:
The reason it's still logging into the account is because the query is still "valid".
The statement will still be executed, and the relevant record will still be returned from the database, no exception will be thrown.
The only way you will stop the login process when invalid data is provided is to validate the input before executing the query. You should always validate user input before sending it off to the database. If the user were to provide:
username'; drop table users;--
as the username, you would be in a LOT of trouble.
The error you're encountering is a debugging error, not an actual program exception. That's why it works when you run it normally.
To remedy the error, I'd first make sure that everything is running with a Debug build. Also, make sure you're currently debugging in the function of the variable you want to inspect. Try stepping (F10) a few times past your breakpoint to refresh the context. There are a slew of other suggestions on the internet for that particular error, so if you're still having problems you might have to do some googling.
Hello
I'm trying to update a ms access database. I've got a gridview with a date that i use:
Dim tBox As TextBox = CType(gridStaff.Rows(e.RowIndex).FindControl("sDate"), TextBox)
I then want to take the value from this textbox and assign it to a date variable.
Dim test As Date = CDate(tBox.Text)
The problem I have is that now when I put test variable into my sql update query it stores the date in this format. mm/dd/yyyy instead of the dd/mm/yyyy format I want.
Ive tried different ways to format it I read online but to no success yet. Any advice would be great!
Thanks
Is your problem the conversion from tBox.Text to Date, or is it at the sql update query level? -- You should probably give the sql statement a parameter with a strict type. Converting from tBox.Text into test should probably be done in a Culture aware manner:
'String to convert and target date:
Dim dateString As String = "02/15/2011"
Dim d As Date
' Specify English/US culture when converting string:
Dim cul As Globalization.CultureInfo = Globalization.CultureInfo.GetCultureInfo("en-US")
d = Date.Parse(dateString, cul)
You could also rely on the default culture and simply let Date.Parse do the job without specifying the culture.
try using
Dim test As Date = DateTime.ParseExact(tBox.Text, "d/M/yyyy", CultureInfo.InvariantCulture)
or if your System is set up right and CultureInfo.CurrentCulture has the right date format,
Dim test As Date = DateTime.Parse(tBox.Text, CultureInfo.CurrentCulture )
instead of CDate()
I'm just stumped on what to do with this code, I'm just trying to implement a 'no duplicates' catch on my insert customer form, but it just slips through my if statement to the else everytime. This is the source. Also I tried a .Equals with the same results :(
Protected Sub srcAllClients_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles srcAllClients.Inserting
'Establish Variables
Dim emailAddress As String
Dim srcUsers As SqlDataSource = New SqlDataSource()
srcUsers.ConnectionString = ConfigurationManager.ConnectionStrings("ISSD21ConnectionString").ConnectionString
Dim view As DataView
view = DirectCast(srcUsers.Select(DataSourceSelectArguments.Empty), DataView)
srcUsers.SelectCommand = "SELECT EmailAddress FROM ISSDClients"
srcUsers.DataSourceMode = SqlDataSourceMode.DataReader
Dim reader As IDataReader
reader = DirectCast(srcUsers.Select(DataSourceSelectArguments.Empty), IDataReader)
emailAddress = FormView1.FindControl("txtEmail").ToString
While reader.Read()
If reader("EmailAddress") = (emailAddress) Then
lblError.Text = "Your Email is NOT Unique!"
'this is where we cancel the update and return an error
Else
lblError.Text = "Your Email is Unique!"
'nothing needs to happen, maybe just tell them that it went through
End If
End While
reader.Close()
End Sub
emailAddress = FormView1.FindControl("txtEmail").ToString
is just going to return the string "System.Web.UI.WebControls.TextBox". You're not accessing the actual property of the control that would hold the text value, you're just calling ToString() on the control itself.
Try this:
Dim emailBox As TextBox = CType(FormView1.FindControl("txtEmail"), TextBox);
emailAddress = emailBox.Text
In addition to Womp's answer...
In the while loop that is running through the email records, you need to break out of the loop once you find a matching email and alert the user.
if reader("EmailAddress") = (emailAddress) then
'1. Break from the Loop
End if
I would recommend that you pass the emailAddress to the SQL Server as a parameter.
Select Count(EmailAddress) From ISSDClients
Where EmailAddress = #EmailAddress
Execute this statement using ExecuteScalar and cast the result as an integer. If the result is zero then you are ok, otherwise display an error.
Doing it this way avoids using the while loop and should be much quicker if your table has lots of rows.
You also need to get the Text property from the Email Text box.
emailAddress = FormView1.FindControl("txtEmail").Text.ToString
You may want to take a look at the String.Compare method, which will make it easier to compare without respect to things like case sensitivity and culture. It does consider whitespace to be part of your string, so you may wish to trim the string prior to calling it, to help normalize.
For example, the following strings would be considered equal:
var firstString = "some StrinG to Compare ";
var secondString = " somE string to COMPARE";
var equal = (String.Compare(firstString.Trim(), secondString.Trim(), StringComparison.InvariantCultureIgnoreCase) == 0);
I'm passing some parameters to a CR report programatically and it was working fine, but now that I have added a new date parameter to the report, for some reason, it is prompting me to enter that parameter on screen (the user isn't allowed to set that parameter is the system who must set it.), I haven't changed a thing other than adding the new date parameter, and all the other parameters behave normal, just the date parameter is prompted even thought I've already set a value for the parameter.
This is the code I've got:
private void ConfigureCrystalReports()
{
crystalReportViewer.ReportSource = GetReportPath();
crystalReportViewer.DataBind();
ConnectionInfo connectionInfo = GetConnectionInfo();
TableLogOnInfos tableLogOnInfos = crystalReportViewer.LogOnInfo;
foreach (TableLogOnInfo tableLogOnInfo in tableLogOnInfos) {
tableLogOnInfo.ConnectionInfo = connectionInfo;
}
ArrayList totOriValues = new ArrayList();
totOriValues.Add(date.ToString("MM/dd/yyyy HH:mm:ss"));
ParameterFields parameterFields = crystalReportViewer.ParameterFieldInfo;
SetCurrentValuesForParameterField(parameterFields, totOriValues, "DateParameter");
}
private static void SetCurrentValuesForParameterField(ParameterFields parameterFields, ArrayList arrayList, string parameterName)
{
ParameterValues currentParameterValues = new ParameterValues();
foreach (object submittedValue in arrayList) {
ParameterDiscreteValue parameterDiscreteValue = new ParameterDiscreteValue();
parameterDiscreteValue.Value = submittedValue.ToString();
currentParameterValues.Add(parameterDiscreteValue);
}
ParameterField parameterField = parameterFields[parameterName];
parameterField.CurrentValues = currentParameterValues;
}
Just for the sake of things: I have checked that the parameter is indeed a date and that it is well formed. CR prompts me to enter it in the format (mm/dd/yyyy hh:mm:ss) so I pass date in that exact format (In fact I've even tried hard coding a well-formed date and it still prompts me to enter the date).
Am I doing something wrong?
I would suggest setting the parameter to an actual DateTime instead of a string. The Value property of ParameterDiscreteValue takes an object. In my reports I set it to a DateTime value and it works fine. I don't work with user prompts at all, but my guess is that the parameter did not get a value it could use, and so raises the prompt.
Yes, Crystal doesn't like strings for dates, so if it is a date field, I would pass in the date in mm/dd/yyyy format, but with a # on both end. So for today I'd pass in #04/01/2010#.