Prevent Duplicate E-mail Address Submissions c# - c#

I have the following c# code below that I am trying to include additional functionality to prevent duplicate e-mail addresses from being entered into the database using an asp.net form. Below is the code, currently it is inserting all entries, duplicate or not, into the database.
using System.Data.OleDb;
using System.Configuration;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["northwind"].ToString();
con.Open();
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail=' " + TextBox2.Text + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
Label1.Text = "email is already in use";
}
else {
cmd.CommandText = "insert into[Table1](pName, pEmail)values(#nm,#em)";
cmd.Parameters.AddWithValue("#nm", TextBox1.Text);
cmd.Parameters.AddWithValue("#em", TextBox2.Text);
cmd.Connection = con;
int a = cmd.ExecuteNonQuery();
if (a>0)
{
Label1.Text = "Inserted Sucessfully!";
}
}
}
}
Asp.net form code
<form id="form1" runat="server">
<div style="height: 138px">
Enter Name:<asp:TextBox ID="TextBox1" runat="server" style="margin-left: 12px"></asp:TextBox>
<asp:RequiredFieldValidator
id="reqName"
ControlToValidate="TextBox1"
Style="color:Red"
ErrorMessage="Please enter your name!"
runat="server" />
<br />
Enter Email:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator
id="ValidEmail"
ControlToValidate="TextBox2"
Style="color:Red"
ValidationExpression="^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"
ErrorMessage="Invalid Email Entry"
runat="server" />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Submit" />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
</div>
</form>

As you are a doing a SELECT statement, you need to the ExecuteScalar method on OleDbCommand to get the results. As per the MSDN documentation, ExecuteScalar returns:
The first column of the first row in the result set, or a null
reference if the result set is empty.
In your case, the return will be the value of COUNT(ID) from your query.
ExecuteNonQuery is for operations which modify data and will return the number of rows affected by the query. As per the MSDN documentation:
You can use the ExecuteNonQuery to perform catalog operations, for
example, to query the structure of a database or to create database
objects such as tables, or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data. For
UPDATE, INSERT, and DELETE statements, the return value is the number
of rows affected by the command. For all other types of statements,
the return value is -1. If a rollback occurs, the return value is also
-1.
So change you code as follows:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail='" + TextBox2.Text + "'"; // note: vulnerable to SQLInjection.
OleDbCommand cmd = new OleDbCommand(query, conn);
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
// etc.
Update: I would also recommend using a Transaction on your operation to make sure that a duplicate email address is not added in between your checking for duplicates and you doing the actual insert.
Update 2:
Based on the updated code that switches to using ExecuteScalar, this line:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail=' " + TextBox2.Text + "'";
Should be:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail='" + TextBox2.Text + "'";
(Extra whitespace character between pEmail=' and " removed.

I think it may be the way you're instantiating the command object, but I'm not in a place to set up a test project to confirm. I think you actually want the ExecuteReader method, or at least that's what I've used in the past for SELECT on the fly like this.
This is what I'm basing it on: OleDbCommand.ExecuteReader
Can you try something like
protected void Button1_Click(object sender, EventArgs e) {
OleDbConnection con = new OleDbConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString2"].ToString();
con.Open();
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= " + TextBox2.Text;
OleDbCommand cmd = new OleDbCommand(query, con);
OleDbDataReader reader = command.ExecuteReader();
int count = 0;
while (reader.Read()) {
count = Convert.ToInt32(reader[0].ToString());
}
reader.Close();
if (count > 0) {
Label1.Text = "email is already in use";
} else {
//re-instantiate the command obj
cmd = new OleDbCommand(); //empty constructor should work, I think
cmd.CommandText = "insert into[Table1](pName)values(#nm)";
cmd.Parameters.AddWithValue("#nm", TextBox1.Text);
cmd.CommandText = "insert into[Table1](pEmail)values(#nm)";
cmd.Parameters.AddWithValue("#nm", TextBox2.Text);
cmd.Connection = con;
int a = cmd.ExecuteNonQuery();
if (a > 0) {
Label1.Text = "Inserted Sucessfully!";
}
}
}

You are trying to check if the email exist with these lines:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= #TextBox2";
int count = cmd.ExecuteNonQuery(query);
but you don't use ExecuteNonQuery to get data from the database, you use ExecuteReader.
Hope this help you with yout issue.

ExecuteNonQuery does not take an argument. Try this:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= #TextBox2";
OleDbCommand cmd = new OleDbCommand(query);
int count = cmd.ExecuteNonQuery();
Also, you are trying to check the return value of ExecuteNonQuery which actually returns the number of rows affected. But that is not the value returned by you SQL statement. If you would like to get the value returned by your SQL statement, you should use ExecuteReader or ExecuteScalar.
And I am not sure if your query is correct either. Shouldn't it be something like:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= " + TextBox2.Text;

Related

Need to update a column in SQL with WHERE using comma separated values from textbox

Just to let you guys know I'm not a programmer # all but I can manage to get code to work sometimes but I'm stumped now. I have a c# web-based project that I finally figured out how to pass comma-separated values from a single textbox to return a result in Datagrid when I click search. The code looks like this:
{
String str = "select row_number() OVER (ORDER BY [sequenceid]) #,[JobNumber],[Item],Quantity,Bay,Trailer,Sequenceid, Produced from vwcabsandcountersbyjob ";
String str1 = "select SUM([Quantity])AS [Items Remaining to Be Loaded] from vwcabsandcountersbyjob";
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str += " WHERE (jobnumber IN ('" + string.Join("','", search.ToArray()) + "') and loaded is null) ORDER BY ITEM DESC";
}
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str1 += " WHERE (jobnumber IN ('" + string.Join("','", search.ToArray()) + "') and loaded is null) ";
}
SqlCommand xp = new SqlCommand(str, vid);
SqlCommand xp1 = new SqlCommand(str1, vid);
//xp.Parameters.Add("#search", SqlDbType.NVarChar).Value = TextBox1.Text;
xp.Parameters.Add("#search", SqlDbType.NVarChar, 20).Value = TextBox1.Text;
xp1.Parameters.Add("#search", SqlDbType.NVarChar).Value = TextBox1.Text;
vid.Open();
xp.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = xp;
DataSet ds = new DataSet();
da.Fill(ds, "[jobnumber]");
GridView1.DataSource = ds;
GridView1.DataBind();
vid.Close();
vid.Open();
xp1.ExecuteNonQuery();
SqlDataAdapter da1 = new SqlDataAdapter();
da1.SelectCommand = xp1;
DataSet ds1 = new DataSet();
da1.Fill(ds1, "[jobnumber]");
GridView2.DataSource = ds1;
GridView2.DataBind();
vid.Close();
}
Now i have a second button that I want to update a field when they press "mark complete". It works fine with a single entry and here is the code:
protected void Button2_Click(object sender, EventArgs e)
{
vid.Open();
SqlCommand xp = new SqlCommand("Update [Job_Master] SET [Completed] = GETDATE() WHERE [job number] =#search", vid);
SqlCommand xp3 = new SqlCommand("Update [Countertops] SET [Completed] = GETDATE() WHERE [jobnumber] =#search", vid);
xp.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp3.Parameters.Add("#search", SqlDbType.NChar).Value = TextBox1.Text;
xp.ExecuteNonQuery();
xp3.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
The problem is it only works for one value. I've tried a million different things but nothing works mainly because I don't know what I'm doing. This is the closest I've come (i added a 3rd button because i didn't want to break button 2 that works for single value):
Protected void Button3_Click(object sender, EventArgs e)
{
String str3 = "Update [Job_Master] SET [Completed] = GETDATE()";
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str3 += " WHERE [job number] IN ('" + string.Join("','", search.ToArray()) + "')";
}
SqlCommand xp4 = new SqlCommand(str3, vid);
vid.Open();
xp4.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp4.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
and it doesn't work. It only updates when I have a single entry. My question is how do use those same values from that textbox work in an update statement? I hope I'm being clear but will try my best to answer any questions but please remember my vocabulary is very limited when it comes to programming. Thanks!
It would be wise if you just divide your code into smaller parts, group them by their role and responsibility. This would make things much easier to maintain and also to work with.
if you see repetitive code, then it's a flag of moving it to a separate method.
A few notes that I've found in your code :
you should use using clause when possible, like using it with SqlConnection, SqlCommand, and SqlDataAdapter.
Multiple unneeded SqlCommand are used.
Providing SqlParamter while the query doesn't have any parameter.
using string concatenation is not optimal, instead use StringBuilder.
Your business logic should have its own methods or classes, and can be recalled inside any event.
Split returns Array, so no need to convert Array to another Array.
Always, each portion of the code, should be scoped to that portion role only. For instance, OnClick event, should handle the click event only, and not handling the update records. The update part should be declared and handled outside the event, and you only recall it from inside the event.
I have updated the code, which would give you a better view on the above notes:
protected void SearchButton_OnClick(object sender, EventArgs args)
{
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrWhiteSpace(TextBox1.Text))
{
SearchAndBind(TextBox1.Text);
}
}
protected void Button2_Click(object sender, EventArgs e)
{
var textValue = TextBox1.Text.Trim();
if(!string.IsNullOrWhiteSpace(textValue))
{
UpdateRecords("UPDATE [Job_Master] SET [Completed] = GETDATE() WHERE [job number] = #search", "#search", textValue);
UpdateRecords("UPDATE [Countertops] SET [Completed] = GETDATE() WHERE [jobnumber] = #search", "#search", textValue);
CompletedJobNotification();
}
}
protected void Button3_Click(object sender, EventArgs e)
{
string inClause = GetInClause(TextBox1.Text);
if(!string.IsNullOrWhiteSpace(inClause))
{
StringBuilder query = new StringBuilder("Update [Job_Master] SET [Completed] = GETDATE()");
query.Append(" WHERE [job number] ").Append(inClause);
UpdateRecords(query.ToString());
CompletedJobNotification();
}
}
private void PopulateData(string query, string srcTable, GridView gridView)
{
if (!string.IsNullOrWhiteSpace(query))
{
using(SqlConnection connection = new SqlConnection(connectionString))
using(SqlDataAdapter adapter = new SqlDataAdapter(query, connection))
{
adapter.Open();
DataSet ds = new DataSet();
da.Fill(ds, srcTable);
gridView.DataSource = ds;
gridView.DataBind();
}
}
}
private string GetInClause(string text)
{
if(!string.IsNullOrWhiteSpace(text))
{
char[] characters = { ',', '\n' };
var ids = text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
return "IN ('" + string.Join("','", ids) + "')";
}
return string.Empty;
}
private void SearchAndBind(string search)
{
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrWhiteSpace(search))
{
string inClause = GetInClause(search);
if(!string.IsNullOrWhiteSpace(inClause))
{
var searchWhere = $" WHERE jobnumber loaded IS NULL AND {inClause} ";
StringBuilder str = new StringBuilder("SELECT ROW_NUMBER() OVER (ORDER BY [sequenceid]) #,[JobNumber],[Item],Quantity,Bay,Trailer,Sequenceid, Produced FROM vwcabsandcountersbyjob");
StringBuilder str1 = new StringBuilder("SELECT SUM([Quantity]) AS [Items Remaining to Be Loaded] FROM vwcabsandcountersbyjob");
str.Append(searchWhere).Append(" ORDER BY ITEM DESC ");
str1.Append(searchWhere);
PopulateData(str.ToString(), "[jobnumber]", GridView1);
PopulateData(str1.ToString(), "[jobnumber]", GridView2);
}
}
}
private void UpdateRecords(string query, string parameterName = null,string parameterValue = null)
{
using(var connection = new SqlConnection(connectionString))
using(var command = new SqlCommand(query))
{
if(!string.IsNullOrWhiteSpace(parameterName) && !string.IsNullOrWhiteSpace(parameterValue))
{
command.Parameters.AddWithValue(parameterName, parameterValue);
}
connection.Open();
command.ExecuteNonQuery();
}
}
private void ShowJavaScriptAlert(string message)
{
if(!string.IsNullOrWhiteSpace(inClause))
{
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", $" window.onload = function(){{ alert('{message}')}}; ", true);
}
}
private void CompletedJobNotification()
{
ShowJavaScriptAlert("This job has been marked complete!");
}
Ok, first up, we are writing too much code here.
Next up, we can MOST certainly have a list of parameters, and they can be optional, and we NEVER concatenate user input into the SQL string - we don't have to.
Now, I don't have the users data, lets do this:
I can type in a city, or several. I will display some hotels, and then ONE button to confirm the hotels and update the database with the confirm date.
(the same as what you are doing).
Ok, so a text box, and a button. Like this:
Search: <asp:TextBox ID="txtPromptCity" runat="server" Height="17px" Width="336px"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="Search City" Style="margin-left:20px" />
So, you can type in one city, or several (with a , in between). Same as what you need/are doing.
Ok, so when you type in and hit search, we send the results to a grid view.
So, we have this code for the button:
DataTable rstHotels = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
rstHotels = (DataTable)ViewState["rstHotels"];
}
protected void cmdSearch_Click(object sender, EventArgs e)
{
string[] strChoices;
strChoices = txtPromptCity.Text.Split(',');
using (SqlCommand cmdSQL = new SqlCommand("",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
string strSQL = "";
int i = 1;
foreach (string strCity in strChoices)
{
if (strSQL != "")
strSQL += ",";
i += 1;
strSQL += "#" + i;
cmdSQL.Parameters.Add("#" + i, SqlDbType.NVarChar).Value = strCity;
}
cmdSQL.CommandText = "SELECT * from tblHotels WHERE City IN (" + strSQL + ")";
cmdSQL.Connection.Open();
rstHotels.Rows.Clear();
rstHotels.Load(cmdSQL.ExecuteReader());
ViewState["rstHotels"] = rstHotels;
GridView1.DataSource = rstHotels;
GridView1.DataBind();
}
}
note how I keep/have the data table - I persist it at the class level.
So, our output is now this
Ok, so we now have the parameter issue working.
Now, all you have to do is check box the ones to approve, and then send the data back to the table - along with the approved visit date.
That code NOW becomes dead simple.
We can use this:
protected void cmdConfirm_Click(object sender, EventArgs e)
{
foreach (GridViewRow gvRow in GridView1.Rows)
{
CheckBox chkVisit = (CheckBox)gvRow.FindControl("chkVisit");
if (chkVisit.Checked)
// update Visit date in table
rstHotels.Rows[gvRow.RowIndex]["VistDate"] = DateTime.Today;
// now send table changes back to database.
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels where ID = 0",
new SqlConnection(My.Settings.TEST4)))
{
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daUpate = new SqlCommandBuilder(da);
da.Update(rstHotels);
}
}
}
So, note how we send the grid choices back to the table, and then send the table back to the database. This makes the whole process easy, and VERY much less code.
And I would probably add a 2-3 lines more code in the Row bound event, and set the checkbox if the row has a date already. And we could I suppose even check if we un-check the checkbox, and again null out the date column row.
All of these are VERY dead easy with the above approach.
So, persisting the table as per above - makes this REALLY easy. And note the data Keys setting - we can use/get/grab the primary key of each row and not have to display it - but this example does not see to need this ability anyway.
The markup I used for above is this:
Search: <asp:TextBox ID="txtPromptCity" runat="server" Height="17px" Width="336px"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="Search City" Style="margin-left:20px" OnClick="cmdSearch_Click" />
<div style="width:45%;margin-top:20px;margin-left:20px">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="VistDate" HeaderText="Visit Date" DataFormatString="{0:yyyy-MM-dd}" />
<asp:TemplateField HeaderText="Confirm Visit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkVisit" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="cmdConfirm" runat="server" Text="Confirm Vists" Width="143px" CssClass="btn-info" OnClick="cmdConfirm_Click" />
<br />
</div>
Thanks for all of the help from everyone. The actual was that my aspx code was pointing to OnClick="Button2_Click" and not OnClick="Button3_Click". Once i fixed that and put in the original code it worked. Having said that you guys have pointed out some great points that i'm going to try and fix. Again, i'm not a programmer and sure appreciate you guys helping. Thanks.
First of all, good job getting as far as you did. I think the only thing left is just a simple mistake. I'll provide this which removes a little of the code you don't need
Protected void Button3_Click(object sender, EventArgs e)
{
String str3 = "Update [Job_Master] SET [Completed] = GETDATE()";
// ** This is a little dangerous. If the TextBox is EMPTY, you will be
// ** Updating ALL rows in the table. I assume that is not what you want.
// ** You should return an error if text box is empty.
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
char[] characters = { ',', '\n' };
char[] invalid = { ',',';',' ','\'','"','\\','\t' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
//
// ** You don't really need to copy into a list.
// ** If you want to trim each entry, you can just
// ** replace in the original array.
for (int i = 0; i < ids.Length; i++)
{
ids[i] = ids[i].Trim();
// ** Add a check here to make sure id is safe
// ** to prevent SQL injection.
if (ids[i].IndexOfAny( invalid ) != -1)
{
return; // should give error, probably.
}
}
// *** figure out if it is job_number or jobnumber or (unlikely) job number
str3 += " WHERE [job_number] IN ('" + string.Join("','", ids) + "')";
}
else {
return; // empty string. Should give error.
}
// ** OPEN FIRST
vid.Open();
SqlCommand xp4 = new SqlCommand(str3, vid);
// ** #search not needed
// xp4.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp4.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
Now, if the IDs are not supposed to be numeric, you have a little more difficulty preventing SQL injection. You'd want to create a parameter for each one (#1, #2, #3, etc...) and add each as a parameter.
Or, of course, you could run a separate SQL statement for each ID. Not super efficient but probably fast enough.

DetailsView Insert behind the code is not working

I'm trying to insert some data in the database through using
detailsView insert command. And Its not working. Here is my code
behind. I manage to successfully insert in the .aspx page buti has some limitations, since I need to use the row of the gridview as data also and I can only accomplish it if I do it in the aspx.cs page.
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
string Price;
string Item;
string PetitionType;
string Note;
string UserNameGV = (GridView1.SelectedRow.Cells[3].Text);
string InvoiceGV = (GridView1.SelectedRow.Cells[5].Text);
string CreatedDateGV = (GridView1.SelectedRow.FindControl("lblLocalTime") as Label).Text;
SearchTB.Text = UserNameGV + " " + InvoiceGV + " " + CreatedDateGV;
DateTime CreatedDate = Convert.ToDateTime(CreatedDateGV);
for (Int32 attempt = 1; ;)
{
using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["RapidVisaConnectionString"].ConnectionString))
{
try
{
Price = ((TextBox)DetailsView1.Rows[1].FindControl("TextBox2")).Text;
Item = ((DropDownList)DetailsView1.Rows[1].FindControl("DropDownList2")).SelectedValue;
PetitionType = ((DropDownList)DetailsView1.Rows[1].FindControl("DropDownList3")).SelectedValue;
Note = ((TextBox)DetailsView1.Rows[1].FindControl("TextBox2")).Text;
con.Open();
string Sql = "INSERT INTO InvoiceDetail (Price, Item, PetitionType, Note, Paid, Quantity, Invoice, UserName, CreatedDate) VALUES (#Price, #Item, #PetitionType, #Note, #Paid, #Quantity, #Invoice, #UserName, #CreatedDate)";
SqlCommand cmd = new SqlCommand(Sql, con);
cmd.Parameters.AddWithValue("#Price", Price);
cmd.Parameters.AddWithValue("#Item", Item);
cmd.Parameters.AddWithValue("#PetitionType", PetitionType);
cmd.Parameters.AddWithValue("#Note", Note);
cmd.Parameters.AddWithValue("#Paid", 1);
cmd.Parameters.AddWithValue("#Quantity", 1);
cmd.Parameters.AddWithValue("#Invoice", InvoiceGV);
cmd.Parameters.AddWithValue("#UserName", UserNameGV);
cmd.Parameters.AddWithValue("#CreatedDate", CreatedDate);
cmd.ExecuteNonQuery();
return;
}
catch (SqlException sqlException)
{
// Increment Trys
attempt++;
// Find Maximum Trys
// Override the web.config setting of 4 for retrys for this method because we are getting time-out errors.
Int32 maxRetryCount = Int32.Parse(ConfigurationManager.AppSettings["ConnectionRetrys"]);
//Int32 maxRetryCount = 5;
// Throw Error if we have reach the maximum number of retries
if (attempt == maxRetryCount)
{
ErrorLog EL = new ErrorLog();
EL.WriteErrorWithSubjectNoWriteToDB("", "Error InvoiceDetail Max Retry");
//going to stop throwing an error because we are getting too many
//throw;
break;
}
// Determine if we should retry or abort.
if (!SQLUtilities.RetryLitmus(sqlException))
{
ErrorLog EL = new ErrorLog();
EL.WriteErrorWithSubjectNoWriteToDB("Insert Failed RetryLitmus for user " + UserName + ". Sql exception number " + sqlException.Number.ToString() + ". " + sqlException.ToString(), "Error InvoiceDetail Failed Litmus");
//going to stop throwing an error because we are getting too many
//throw;
break;
}
else
Thread.Sleep(SQLUtilities.ConnectionRetryWaitSeconds(4));
//Changed from default of 5 seconds to 3 seconds
//Thread.Sleep(SQLUtilities.ConnectionRetryWaitSeconds(attempt));
}
}
}
}
Here is the error message that I got.
Inserting is not supported by data source 'DetailsViewDS' unless
InsertCommand is specified. The problem is I dont want to add InsertCommand in aspx page , only in aspx.cs
I've tested your code, did some modifications and it works. I've used table of my db, you can modify it according to your need. Modify your SqlDataSource and C# code within DetailsView1_ItemInserting as mentioned below. It will work perfectly.
SqlDataSource:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM [Image]" InsertCommand="INSERT INTO [Image] ([Name]) VALUES (#Name)">
<InsertParameters>
<asp:Parameter Name="Name" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
Insertion from code behind
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
SqlDataSource sqldsInsertPassword = new SqlDataSource();
sqldsInsertPassword.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
sqldsInsertPassword.ProviderName = ConfigurationManager.ConnectionStrings["ConnectionString"].ProviderName;
sqldsInsertPassword.InsertCommand = "INSERT INTO Image (Name) VALUES (#Name)";
sqldsInsertPassword.InsertCommandType = SqlDataSourceCommandType.Text;
sqldsInsertPassword.InsertParameters.Add("Name", e.Values[0].ToString());
sqldsInsertPassword.Insert();
}
I hope it will solve your issue.
Regards!

Show data in Textboxes from database in C#

Is there anything wrong with my code? It is not showing data in textboxes. The same funtion is working for another table in database but not for this one.
private void metroButton1_Click(object sender, EventArgs e)
{
con = new SqlConnection(constr);
String query = "Select FROM Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
cmd = new SqlCommand(query, con);
con.Open();
try
{
using (SqlDataReader read = cmd.ExecuteReader())
{
while (read.Read())
{
// metroTextBox1.Text = (read["ID"].ToString());
metroTextBox2.Text = (read["Name"].ToString());
metroTextBox3.Text = (read["F_Name"].ToString());
metroTextBox4.Text = (read["Std_Age"].ToString());
metroTextBox5.Text = (read["Address"].ToString());
metroTextBox6.Text = (read["Program"].ToString());
metroComboBox1.Text = (read["Course"].ToString());
}
}
}
finally
{
con.Close();
}
}
you need to give column names in the select statement or select *
for example :
String query = "Select * from Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
Not related to Question: you can change the while loop to if condition if you have one record for given id. even there are many records for given id you will see the last record data only because of the while loop will overwrite the textboxes in every record.
Update :
There isn't anything wrong with Syntax because the same syntax is
working for modifying teacher funtion.
No, this is incorrect, remove the try catch in your code then you will see the exception of syntax error

How to use the GridView AutoGenerateDeletebutton

I am using Visual Studio 2010 to develop an asp.net app using c#. I created an GridView table by the following
<asp:GridView ID="GridView1" runat="server" AutoGenerateDeleteButton="True"
EnableViewState="False" OnRowDeleting="DeleteRowButton_Click">
</asp:GridView>
But I do not know how to use the auto generated delete button in my c# code.
I search online, they always provide my code as
protected void DeleteRowButton_Click(Object sender, GridViewDeleteEventArgs e)
{
var PN = GridView1.DataKeys[e.RowIndex].Values["Part_Number"];
string PN = pn.ToString;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["XMLConnectionString"].ConnectionString);
// Create the command object
con.Open();
string str = "DELETE * FROM XML WHERE ([Part_Numbber] = " + PN + ")";
SqlCommand cmd = new SqlCommand(str, con);
cmd.ExecuteNonQuery();
Button1_Click(sender, e);
con.Close();
}
Thank you very much for anyone can tell me how to do it
For Delete any record from you should have any unique or Primary key. If you want to delete record using field "Part_Numbber" then this field data-type should be of either int or bigint in Database Table. Then Now put the following code to Delete.
protected void DeleteRowButton_Click(Object sender, GridViewDeleteEventArgs e)
{
int Part_Numbber= Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
SqlCommand cmd = new SqlCommand("DELETE FROM XML WHERE Part_Numbber=" + Part_Numbber+ "", con);
con.Open();
int temp = cmd.ExecuteNonQuery();
if (temp == 1)
{
lblMessage.Text = "Record deleted successfully";
}
con.Close();
FillGrid();
}
How this may help you.

Search with autocomplete and Ajax

I want to make a search like them from google.
I've made it this far, that I can show all data from the database in my textbox with using a webservice. Thats my code:
Webform.aspx
<%--**Start Search**--%>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services><asp:ServiceReference Path="~/WebService.asmx" /></Services>
</asp:ScriptManager>
<%--Search-Textbox--%>
<asp:TextBox runat="server" ID="txtSearchInput" Width="100%" />
<asp:Button ID="btnSearch" runat="server" Text="Suche" onclick="btnSearch_Click" />
<%--Autocomplete (Ajax)--%>
<asp:AutoCompleteExtender ID="AutoComplete1" runat="server" TargetControlID="txtSearchInput"
ServiceMethod="GetNames" ServicePath="~/WebService.asmx" MinimumPrefixLength="1"
EnableCaching="true" CompletionInterval="1000" CompletionSetCount="20">
</asp:AutoCompleteExtender>
<%--**End Search**--%>
Webservice.asmx
[WebMethod]
public string[] GetNames(string prefixText, int count)
{
List<string> items = new List<string>(count);
DataSet ds = new DataSet();
string cs = ConfigurationManager.ConnectionStrings["CSLinker"].ConnectionString;
using (SqlConnection connection = new SqlConnection(cs))
{
string sql = "SELECT Name FROM tabProjects WHERE Name LIKE '" + prefixText + "%' UNION all SELECT Name FROM tabLinks WHERE Name LIKE '" + prefixText + "%'";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(sql, connection);
adapter.Fill(ds);
}
foreach (DataRow dr in ds.Tables[0].Rows)
{
items.Add(dr["Name"].ToString());
}
return items.ToArray();
}
My problem now is, that i only have the name from the database. But for the search I need also the ID. Can somebody say me, how I can also query the ID without showing it in the textform?
I hope you can understand my problem. My english isnt' so good...
Thanks for helping!
Why not just pass the project name as the parameter rather than the probject ID? If you are using Response.Redirect I am assuming the user selects a project from the list of selections and the code behind handles somekind of event:
public void onProjectSelected()
{
string cs = ConfigurationManager.ConnectionStrings["CSLinker"].ConnectionString;
string projectName = txtSearchInput.Text;
int projectID = 0;
using (SqlConnection connection = new SqlConnection(cs))
{
using (SqlCommand command = new SqlCommand("SELECT ProjectID FROM TabProjects WHERE Name = #Name", connection))
{
command.Parameters.Add(new SqlParameter("#Name", SqlDbType.VarChar, 50)).Value = projectName;
connection.Open();
if (int.TryParse(command.ExecuteScalar().ToString(), out projectID))
{
Response.Redirect(string.Format("?ProjectID={0}", projectID));
}
connection.Close();
}
}
//Handle project not found events here
}
Also USE PARAMATERISED QUERIES otherwise SQL Injection could ruin your day!
If I were to type "It's a test" into your text box you would end up with an invalid SQL statement as the apostrophe I have used will result in the following SQL.
SELECT Name FROM tabProjects WHERE Name LIKE 'It's a test%'
Which clearly won't run and will not be a great user experience for anyone using your website. More seriously though, if I were to type into the text box on your page '; DROP TABLE TabProjects -- you may find, depednding on the permissions assigned to the CSLinker connection string, that you no longer have an tabProjects table as this is the SQL that is run:
SELECT Name FROM tabProjects WHERE Name LIKE ''; DROP TABLE tabProjects -- %'
You should use something like this for your web method:
[WebMethod]
public string[] GetNames(string prefixText, int count)
{
List<string> items = new List<string>();
string cs = ConfigurationManager.ConnectionStrings["CSLinker"].ConnectionString;
using (SqlConnection connection = new SqlConnection(cs))
{
using (SqlCommand command = new SqlCommand("SET ROWCOUNT #Count SELECT Name FROM TabProjects WHERE Name LIKE #Name + '%'", connection))
{
command.Parameters.Add(new SqlParameter("#Name", SqlDbType.VarChar, 50)).Value = prefixText;
command.Parameters.Add(new SqlParameter("#Count", SqlDbType.Int, 8)).Value = count;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
items.Add(reader.GetString(0));
}
}
connection.Close();
}
}
return items.ToArray();
}

Categories

Resources