简体   繁体   中英

SqlException: Conversion failed when converting date and/or time from character string

I get this error when using a C# webform that "adds" a users Credit card details. The following is my code for the button "Add credit card" on my aspx.cs page

protected void Button1_Click(object sender, EventArgs e)
{
    //declare and initialize connection object to connect to the database
    SqlConnection conn = new SqlConnection(
        WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
    SqlCommand cmd; //declare a command object that will be used to send commands to database.

    conn.Open(); //open a connection to the database
    cmd = conn.CreateCommand(); //create a command object

    cmd.CommandText = "Insert into CreditCard Values ('" +
        txtCCNo.Text + "', '" +
        txtFName.Text + "', '" +
        txtMidInitial.Text + "', '" +
        txtLName.Text + "', '" +
        txtExpirationDate.Text + "', '" + txtType.Text + "', " +
        txtCVC.Text + ", '" + txtIsDefault.Text + "', '" +
        Session["userID"].ToString() + "')";
    cmd.CommandType = CommandType.Text;
    cmd.ExecuteNonQuery();
    conn.Close();

    // added for navigation
    Response.Redirect("~/selectCC.aspx");
}

The following is the main .aspx page

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="AddCC.aspx.cs" Inherits="AddCC" %>

<table style="width: 100%;">
    <tr>
        <td>&nbsp;<asp:Label ID="Label1" runat="server" Text="First Name"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtFName" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="First Name is Required" ControlToValidate="txtFName"></asp:RequiredFieldValidator></td>
    </tr>
    <tr>
        <td>&nbsp;<asp:Label ID="Label2" runat="server" Text="Last Name"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtLName" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="Last Name is Required" ControlToValidate="txtLName"></asp:RequiredFieldValidator></td>
    </tr>
    <tr>
        <td>&nbsp;<asp:Label ID="Label3" runat="server" Text="Middle Initial"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtMidInitial" runat="server" MaxLength="1"></asp:TextBox></td>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;<asp:Label ID="Label4" runat="server" Text="Credit Card No"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtCCNo" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ErrorMessage="Credit Card is Required" ControlToValidate="txtCCNo"></asp:RequiredFieldValidator></td>
 </tr>
 <tr>
        <td>&nbsp;<asp:Label ID="Label5" runat="server" Text="Expiration Date"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtExpirationDate" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="Expiration Date is Required" ControlToValidate="txtExpirationDate"></asp:RequiredFieldValidator></td>
 </tr>
 <tr>
        <td>&nbsp;<asp:Label ID="Label6" runat="server" Text="CVC"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtCVC" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator5" runat="server" ErrorMessage="CVC is Required" ControlToValidate="txtCVC"></asp:RequiredFieldValidator></td>
 </tr>
 <tr>
        <td>&nbsp;<asp:Label ID="Label7" runat="server" Text="Type"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtType" runat="server"></asp:TextBox></td>
        <td>&nbsp;<asp:RequiredFieldValidator ID="RequiredFieldValidator6" runat="server" ErrorMessage="Type is Required" ControlToValidate="txtType"></asp:RequiredFieldValidator></td>
</tr>

    <tr>
    <td>&nbsp;<asp:Label ID="Label8" runat="server" Text="Default"></asp:Label></td>
        <td>&nbsp;<asp:TextBox ID="txtIsDefault" runat="server"></asp:TextBox></td>
        <td>&nbsp;</td>
 </tr>
    <tr>
    <td></td>
    <td>
        <asp:Button ID="Button1" runat="server" Text="Add Credit Card" OnClick="Button1_Click" OnCommand="Button1_Command" /></td>
  <td></td>
    </tr>       
</table>

I believe the error is coming since the ExpirationDate has a DateTime data type but not sure how to specify this within the aspx.cs code so that it is handled by the SQL code.

The proper way is using a parametized query for insert and the SqlParameter class to specify the parameters values. It will also take care of date formats for different languages. And will protect you from a nice SQL injection,

// 1. declare command object with parameter

SqlCommand cmd = new SqlCommand("select * from Customers where city = @City", conn);
// 2. define parameters used in command object
SqlParameter param  = new SqlParameter();
param.ParameterName = "@City";
param.Value = inputCity;

Remember:

http://imgs.xkcd.com/comics/exploits_of_a_mom.png

First, always try and use parameters, even if you are doing this dynamic SQL creation, It will protect you from SQL Injection.

Second, try and grab the value of the txtExpirationDate.Text first, then cast it as DateTime. Try and use an standard format to send the value into your sql Query, it could be that the string format is not recognized (send something like '2015/03/03' for example).

Take a look at the DateTime.Parse() and DateTime.ParseExact() methods for ways to parse a string into a date.

The stuff people are saying about SQL injection is extremely important. If you construct the sql query yourself by just adding a bunch of strings one after each other, you are bound to be open for nasty attacks, if people type carefully crafted strings into the controls that feed the sql query. @Oscar's comment speaks of this risk (someone can type in a value that leads to dropping your whole database) and his answer shows you how to use parameters instead.

The SqlParameter mechanism guards against this, because when the parameter value is being substituted into the query string in place of the @Parameter placeholder, there is code that first carefully sanitizes the parameter value before the substitution.

You basically don't ever want to construct your own sql string by concatenation if you have any safer options.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM