Attempting to create shopping cart remove button - asp.net

Note: This code actually codes from a tutorial book I'm reading at the moment, so you can imagine this is frustrating me greatly! I'm building a basic shopping cart, using VB.NET 4, Visual Studio 2010 and MS SQL Server R2 2008. The code below is supposed to remove items from the cart, by reading a session variable, editing it to remove the appropriate ProductID and return the amending string to the session variable. It is then supposed to rebind the data to the gridview (gvCart) to refresh the data...but it seems here there is an error.
Every time I build the site in Visual Studio, it validates fine. But every time I run the site, and attempt to use the remove button it gives me the error:
Incorrect syntax near ')'.
with the IDE pointing me toward the final parenthesis.
I have been pulling my hair out at this for a good 4 hours now, any advice appreciated!
Protected Sub gvCart_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gvCart.SelectedIndexChanged
'This method is hooked to the Remove button & is removing items from the cart
Dim strProductId As String = gvCart.SelectedRow.Cells(1).Text
If Session("Cart") IsNot Nothing Then
'Remove selected ProductID from Session string and retrieve session string
Dim strCart As String = Session("Cart").ToString()
Dim arIDs As String() = strCart.Split(",")
'Iterate through ID's in the 'Cart' array and rebuild the string leaving out the selected ID
strCart = String.Empty
For Each str As String In arIDs
'use Trim to remove leading and trailing spaces
If str.Trim() <> strProductId.Trim() Then
strCart += str + ", "
End If
Next
'Remove trailing space and comma
If strCart.Length > 1 Then
strCart = strCart.Trim()
strCart = strCart.Substring(0, strCart.Length - 1)
End If
'Put back into session var
Session("Cart") = strCart
'Rebind gvCart, which forces the sqldatasource to requery
gvCart.DataBind()
End If
End Sub
[EDIT]
I am also including the code that runs for the event sqlCart_Selecting for completion sake:
Protected Sub sqlCart_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs) Handles sqlCart.Selecting
Trace.Warn("sqlCart_Selecting") 'aids debugging
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
End Sub
[EDIT]
Also including the SQL query used by the gridview 'gvCart' and the code for displaying the carts contents on another page
<asp:SqlDataSource ID="sqlCart" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT product.ProductID, product.Name, product.ProductNumber, product.Color, subcat.Name AS SubcategoryName, cat.Name AS CategoryName, description.Description FROM Production.Product product JOIN Production.ProductSubcategory subcat ON product.ProductSubcategoryID = subcat.ProductSubcategoryID JOIN Production.ProductCategory cat ON subcat.ProductCategoryID = cat.ProductCategoryID JOIN Production.ProductModel model on product.ProductModelID = model.ProductModelID JOIN Production.ProductModelProductDescriptionCulture culture ON model.ProductModelID = culture.ProductModelID JOIN Production.ProductDescription description ON culture.ProductDescriptionID = description.ProductDescriptionID"></asp:SqlDataSource>
Protected Sub btnAddToCart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddToCart.Click
'The contents of the cart will be saved in a Session object as a string of coma-delimited values of ProductID's
Dim strCart As String = String.Empty
Dim strProductID As String = gvProducts.SelectedDataKey.Value.ToString()
If Session("Cart") Is Nothing Then
strCart = strProductID
Else
strCart = Session("Cart").ToString() + ", " + strProductID
End If
Session("Cart") = strCart
lblCart.Text = strCart
End Sub

I will take a shot here, since you are not showing us everything (the SQL query for instance).
But it feels like the SQL query is using IN clause. And it appears to be failing when the cart goes empty.
Since Session("Cart") contains the comma separated values of the product IDs, an empty list would make the following SQL query fail:
select id, name
from products
where id in ()
with the message:
Incorrect syntax near ')'.
You have to show us the portion of code that's reloading the query from Session("Cart"). The query should be reassembled.
But there's one trick you can use! If your product ids are numeric and always greater than zero, change this line:
strCart = String.Empty
to this:
strCart = '-1, '
Update
I will really teach how to fish on this one. :) the problem is here:
Dim strCart As String = String.Empty
If Session("Cart") IsNot Nothing Then
strCart = Session("Cart").ToString
e.Command.CommandText &= " WHERE product.ProductID IN (" + strCart + ") AND culture.CultureID = 'en'"
Else
e.Cancel = True
End If
When cart is empty, Session("Cart") is not Nothing but it's an empty string (provided that you removed the -1 workaround). If Session("Cart") is an empty string the where clause should be " WHERE culture.CultureID = 'en'" only, no mention to product ids. God speed!

Related

How can I compare a text box entry against a list of database values in the Text_Changed event

as the title states I am trying to compare or validate a text box entry against a list of acceptable values stored in my database. As of now I have taken the values from my database and store them in a List(of String) and I have a for loop that loops through that list and returns true if the values match, if the values do not match it will return false. Below I have attached the code I am currently working with.
Protected Sub txtSearchOC_TextChanged(sender As Object, e As EventArgs) Handles txtSearchOC.TextChanged
Dim listEType As List(Of String) = New List(Of String)
Dim eType As String = txtSearchOC.Text
Dim strResult As String = ""
lblPrefix.Text = ""
lblList.Text = ""
Dim TypeIDQuery As String = "
SELECT a.OrderCode
FROM SKU AS a
INNER JOIN EnrollmentType AS e ON a.EnrollmentTypeID = e.TypeID
INNER JOIN Enrollment AS f ON e.RecID = f.EnrollmentTypeID
WHERE f.AccountNumber = '12345';
"
Using connEType As New SqlConnection(ConfigurationManager.ConnectionStrings("WarrantyConnectionString").ToString)
Using cmdEType As New SqlCommand(TypeIDQuery, connEType)
cmdEType.Parameters.Add("#AccountNumber", SqlDbType.VarChar, 15).Value = "12345"
connEType.Open()
Using sdrEType As SqlDataReader = cmdEType.ExecuteReader
While sdrEType.Read
listEType.Add(sdrEType("OrderCode").ToString)
End While
End Using
End Using
End Using
For Each Item As String In listEType
strResult &= Item & ", "
Next
For i = 0 To listEType.Count - 1
If eType = listEType(i) Then
lblPrefix.Text = "True"
End If
If eType <> listEType(i) Then
lblList.Text = "Error"
End If
Next
'lblList.Text = strResult
End Sub
In the code I declare my list and a variable to store the text value of the text box. To verify that it pulled the appropriate values from the database I have the strResult variable and can confirm that the appropriate values are being stored.
The problem I am having has to do with the For loop I have at the bottom, when I enter in a valid value that is contained in the listEType, I get the confirmation message of "True" indicating it has matched with one of the values, but I also get the "Error" message indicating that it does not match. If I enter in a value that is not contained in the list I only get the "Error" message which is supposed to happen.
My question is, based on the code I have supplied, why would that For loop be returning both "True" and "Error" at the same time for a valid entry? Also, if there is a better way to accomplish what I am trying to do, I am all ears so to speak as I am relatively new to programming.
Well, as others suggested, a drop down (combo box) would be better.
However, lets assume for some reason you don't want a combo box.
I would not loop the data. You have this amazing database engine, and it can do all the work - and no need to loop the data for such a operation. Why not query the database, and check for the value?
Say like this:
Protected Sub txtSearchOC_TextChanged(sender As Object, e As EventArgs) Handles txtSearchOC.TextChanged
If txtSearchOC.Text <> "" Then
Dim TypeIDQuery As String = "
SELECT a.OrderCode FROM SKU AS a
INNER JOIN EnrollmentType AS e ON a.EnrollmentTypeID = e.TypeID
INNER JOIN Enrollment AS f ON e.RecID = f.EnrollmentTypeID
WHERE f.AccountNumber = #AccoutNumber;"
Using connEType As New SqlConnection(ConfigurationManager.ConnectionStrings("WarrantyConnectionString").ToString)
Using cmdEType As New SqlCommand(TypeIDQuery, connEType)
cmdEType.Parameters.Add("#AccountNumber", SqlDbType.NVarChar).Value = txtSearchOC.Text
connEType.Open()
Dim rstData As New DataTable
rstData.Load(cmdEType.ExecuteReader)
If rstData.Rows.Count > 0 Then
' we have a valid match
lblPrefix.Text = "True"
Else
' we do not have a valid match
lblPrefix.Text = "False"
End If
End Using
End Using
End If
End Sub
So, pull the data into a data table. You can then check the row count, or even pull other values out of that one row. But, I don't see any need for some loop here.

ASP.NET - parametrize query for SqlDataSource in ASP.NET code behing- VB.NET / Visual Studio 2010

I am creating a query for a SqlDataSource in ASP.NET from code behind.
My code is as following:
Dim SqlDataSource1 As New SqlDataSource()
Dim SQL As String
' If Not IsPostBack Then
SqlDataSource1.ID = "sqlexpsearch"
Me.Page.Controls.Add(SqlDataSource1)
Dim connectionString As String
Dim connection As SqlConnection
connectionString = ConfigurationManager.ConnectionStrings("exam2ndconnection").ToString
connection = New SqlConnection(connectionString)
SqlDataSource1.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("exam2ndconnection").ConnectionString
If opname.Checked = True Then
SQL = "select SRNO,tr_date as Date ,MailMethod,SpeedId,Content,ExYear,Exroll as No,NAME,Address from dispatch where name = '%'+ #srname +'%' OR ADDRESS ='%'+ #srname +'%' order by TR_DAte DESC,NAME "
SqlDataSource1.SelectParameters.Add("#srname", UCase(txtitem.Text))
SqlDataSource1.SelectCommand = SQL
End If
If opchno.Checked Then
SqlDataSource1.SelectCommand = "select SRNO,tr_date as Date ,MailMethod,SpeedId,Content,ExYear,Exroll as No,NAME,Address from dispatch where rtrim(exroll) ='" & txtitem.Text & "' order by tr_Date,exroll desc"
End If
GridView1.DataSource = SqlDataSource1
GridView1.DataBind()
I get this error:
Must declare the scalar variable "#srname".
on the line of code:
Gridview1.DataBind()
Please help to resolve this problem.
I would avoid trying to inject (add) a sql datasource into a page. (they don't persist anyway - you would have to re-inject each time).
However, DO keep in mind that any data aware control ALWAYS will automatic persist for you anyway.
The above information is thus great, since then you don't even have to bother with the sql data source. This is especially so in your example - you want to fill out a dropdown list, a grid view - whatever. In those cases? Just shove into that control a datatable - and your off to the races.
As noted, a lot of us use + prefer using code in place of a data source on the page - I find them rather messy and a pain to work with anyway.
In fact, what I will often do is say drop in a listbox, or even a grid view. I then use the wizard to create new data source - lay out the grid real nice and fast. I then go into the markup, remove the data source conrol that appears in the page.
Also, don't forget to remove the DataSourceID = from the Gridview markup (or whatever control you using).
This lets me still use the wizards to create the gridview, listview etc. but then I delete that extra junk, and wind up with a nice clean page without all that extra stuff in the page - (which is a pain to control from code anyway).
So, say for your example?
Try coding it this way:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(ConnectionStrings("exam2ndconnection").ConnectionString)
Dim strSQL As String = ""
strSQL = "SELECT SRNO, tr_date as Date, MailMethod, SpeedId, Content, ExYear, Exroll as No, " &
"[Name], Address FROM dispatch "
Dim strWhere As String = ""
Using cmdSQL As New SqlCommand(strSQL, conn)
If opName.Checked Then
strWhere = "([Name] Like '%'+ #srname +'%' OR ADDRESS = '%'+ #srname +'%') "
cmdSQL.Parameters.Add("#srname", SqlDbType.NVarChar).Value = txtitem.Text
End If
If opchno.Checked Then
If strWhere <> "" Then strWhere &= " AND "
strWhere &= "(Rtrim(exroll) = #exroll)"
cmdSQL.Parameters.Add("#exroll", SqlDbType.NVarChar).Value = txtitem.Text
End If
If strWhere <> "" Then
cmdSQL.CommandText &= " WHERE " & strWhere
End If
' add our sorting
cmdSQL.CommandText &= " ORDER BY tr_Date, exroll DESC"
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
A few things:
YES DO NOT forget to put the load of such data inside of the PostBack = false.
Load the results into a datatable (there are several reasons for this, but one BIG reason is that the row data bound event will have full use of that data row - including the WHOLE data row - even columns that are NOT part of the gridview.
note careful in above.
If you don't check "opname", then the criteria is not added.
if you don't check "opchno", then the criteria is not added.
if you check either one - the criteria for that option is added
so, if you check none, no criteria
if you check both, then you get both filters. So this allows you add even more options, and they are ALL optional - and we "clumative" can build up selection criteria this way.

'Initializing data table before use'

how can i solve this please ?
i am doing a simple database project and i have a search field i wrote the following code for searching and displaying data in DataGridView but the
Null Reference Exception keeps showing up because i'm initializing the table with nothing and yet if i don't do so i get 'Used Before Initializing warning.
the question is :how can i initialize the table properly .
Private Sub txtSearch_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearch.TextChanged
Dim searchText As String = txtSearch.Text
Dim matchText As String = ""
Dim rowMatch As Boolean = False
Dim foundRows As DataTable = Nothing 'this initializig causes the problem of null exception,But how can i Initialize it then?????
For Each rw As DataRow In dataSet.Tables(0).Rows
Dim cl As String = rw.Item(1).ToString ' this cell is FirstName Cell
If searchText.Length > cl.ToString.Length Then
matchText = cl.ToString
Else
matchText = cl.ToString.Substring(0, searchText.Length)
End If
'bellow it adds the Found Row (rw) to the table
If (searchText.Equals(matchText) And searchText <> "" And Not foundRows Is Nothing) Then foundRows.Rows.Add(rw)
Next
'to shows data if the search text field is not empty then show the found matching rows
If (searchText <> "") Then
contactView.DataSource = foundRows
Else ' else show the original tavle again
contactView.DataSource = dataSet.Tables(0)
End If
contactView.Refresh() 'refresh
End Sub
here is the screenshot of the form
i tried to use
Dim foundRows As DataTable = New DataTable
but it shows ArgumentException
This Row already belongs to another Table
i also tried this
but as you can see nothing works please Help !
Yes
i finally got it
i was having a problem in columns
Dim foundRows As DataTable = New DataTable("PseuContact") 'this initializig causes the problem of null exception,But how can i Initialize it then?????
foundRows.Columns.Add("ID")
foundRows.Columns.Add("First Name")
foundRows.Columns.Add("Last Name")
foundRows.Columns.Add("Phone Number")
foundRows.Columns.Add("Mobile Number")
foundRows.Columns.Add("Email Address")
initializing columns is important when declaring new table
this's been the best

Changing DropDown Selected Item Based on Selected Value (ASP.NET)

I have a dropdown list on my page (ddlProgram) which is populated via a database query like so:
Using dbContext as IRFEntities = New IRFEntities
Dim getPrograms = (From p in dbContext.IRF_Program _
Order By p.name _
Select p)
ddlProgram.DataSource = getPrograms
ddlProgram.DataTextField = "name"
ddlProgram.DataValueField = "id"
ddl.Program.DataBind()
End Using
So, for example, one might have a DataTextField of "Education" and an ID of "221".
Now, I prepopulate the form with information about the individual visiting the site (if available) - including the dropdown list like so:
If getProspect IsNot Nothing Then
If getProspect.user_id Is Nothing Then
ddlProgram.SelectedValue = getProspect.Program
End If
End If
The Program property contains a number that matches the ID of a Program. So, for example, this individual might have a Program of "221" which would match the "221" of Education mentioned above.
Currently the application successfully sets the SelectedValue to "221" for the DropDownList (ddlProgram), but the SelectedItem of the DDL remains the same (e.g., if it is initially "History" with an ID of "1" after the prepopulation it is "History" with an ID of "221").
What I'm trying to make happen is that the SelectedItem is updated to item which corresponds with the SelectedValue. So, in the end, if the individual has "221" for "Education" selected when the form is prepopulated they would see Education as the selected item and the selected value would be set correctly, whereas right now the form is showing the wrong SelectedItem but has the right SelectedValue behind the scenes.
Here is a more complete idea of the code flow from the Page_Load event:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack = False Then
' If prospect is coming from unique url
Dim prospect_url As String = Page.RouteData.Values("value")
' Save prospect_url into session variable
Session("prospect_url") = prospect_url
Using dbContext As IRFEntities = New IRFEntities
' Prepopulate the programs dropdown.
Dim getPrograms = (From p In dbContext.IRF_Program _
Order By p.name _
Select p)
ddlProgram.DataSource = getPrograms
ddlProgram.DataTextField = "name"
ddlProgram.DataValueField = "id"
ddlProgram.DataBind()
End Using
Using dbContext As IRFEntities = New IRFEntities
' Prepopulate the states dropdown.
Dim getStates = (From p In dbContext.IRF_States _
Order By p.name _
Select p)
ddlState.DataSource = getStates
ddlState.DataTextField = "name"
ddlState.DataValueField = "id"
ddlState.DataBind()
End Using
Using dbContext As IRFEntities = New IRFEntities
' Grab info. about prospect based on unique url.
Dim getProspect = (From p In dbContext.IRF_Prospects _
Where p.url = prospect_url _
Select p).FirstOrDefault
' If they have a record...
If getProspect IsNot Nothing Then
If getProspect.user_id Is Nothing Then
' Prepopulate the form with their information.
' These must have a value, so we need to make sure that no column is null in the database.
ddlProgram.SelectedValue = getProspect.program
txtFirst.Text = getProspect.first_name
txtLast.Text = getProspect.last_name
txtAddress.Text = getProspect.address
txtCity.Text = getProspect.city
ddlState.SelectedValue = getProspect.state
txtZip.Text = getProspect.zip
txtPhone.Text = getProspect.phone
txtEmail.Text = getProspect.email_address
txtYearEnrolling.Text = getProspect.enrolling_in
Else
' Redirect them to login.
Response.Redirect("login.aspx")
End If
End If
End Using
End If
End Sub
What you're doing looks like it should work. If you put a breakpoint after the setting of the value and check the SelectedItem text and value, do they appear as expected or mismatched?
Use the Immediate Window to check:
ddlProgram.SelectedItem.Text
ddlProgram.SelectedItem.Value
If they appear the same then I would presume the binding code is being refired and the list is being regenerated with the first item being selected.
To check this put a break point on the binding code and see if it is fired more than once and correct the order of the methods appropriately.
ADDED:
If it works on your local environment it should work when published, if the code is the same? Looking at your code, I'd start by seperating out some of the databinding code into seperate methods rather than have everything in Page_Load, one becuase it's good practice and two because it will make debugging easier. Further than that I'm not sure what else to suggest.

ASP CascadingDropDown Control Causes IE Script timeout

Before a page is loaded, I use a subroutine to link DropDownList controls together:
Private Sub CreateCascadingDropDown(ByVal category As String, ByRef parentDDL As DropDownList, ByRef targetDDL As DropDownList)
Dim CDDL As New CascadingDropDown
With CDDL
.Category = category
If Not parentDDL Is Nothing Then
parentDDL.Items.Clear()
.ParentControlID = parentDDL.ID
End If
targetDDL.Items.Clear()
.TargetControlID = targetDDL.ID
.PromptText = SharedWeb.GC_SELECTONE
.PromptValue = "-1"
.LoadingText = "Please wait..."
.ServicePath = "/ajax/InvestmentProcess.asmx"
.ServiceMethod = "GetTaxo"
End With
'Page.ClientScript.RegisterForEventValidation(CDDL.UniqueID)
targetDDL.Parent.Controls.Add(CDDL)
End Sub
When the web service method is called, it executes the following code. Based on the category, it gets the appropriate data from the adapter.
<WebMethod()> _
Public Function GetTaxo(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue()
Dim log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
log.Debug("GetSegmentTaxonomy(" + category + ") -> {" + knownCategoryValues + "}")
Dim kv As StringDictionary = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues)
Dim adapter As New SegmentTaxonomyTableAdapters.SEGMENT_ARCHITECTURE_TableAdapter
Dim rows As DataRowCollection
Select Case category
Case InvestmentEdit.ST_SEG_ARCH
rows = New SegmentTaxonomyTableAdapters.SEGMENT_ARCHITECTURE_TableAdapter().GetData().Rows
Case InvestmentEdit.ST_LOB
If kv.ContainsKey(InvestmentEdit.ST_SEG_ARCH) Then
log.Debug("found seg architecture - > " + kv(InvestmentEdit.ST_SEG_ARCH))
rows = New SegmentTaxonomyTableAdapters.LINE_OF_BUSINESSTableAdapter().GetData(kv(InvestmentEdit.ST_SEG_ARCH)).Rows
End If
End Select
If Not rows Is Nothing Then
Dim results As New List(Of CascadingDropDownNameValue)
For Each row As DataRow In rows
log.Debug("ROW >>>> " + row("lov_label").ToString() + " : " + row("lov_cd").ToString())
results.Add(New CascadingDropDownNameValue(row("lov_label"), row("lov_cd")))
Next
Return results.ToArray
End If
Return Nothing
End Function
There are about 5 drop downs I need to link together. The top-level drop down control (myDDL) loads fine if it is the only one linked like so:
CreateCascadingDropDown("MyCat",Nothing,myDDL)
But when I link a second drop down control, Internet Explorer gives a script timeout. If I keep allowing the script to run, it just keeps giving me the prompt. If elect to discontinue running the script, I get a Method Error 12031 or Error 500 (and yes, I have the ScriptService() declaration in my web service file). Any ideas on what's causing this?
It turns out I just needed to add the following control from the Ajax Control Toolkit:
<ajax:ToolkitScriptManager ID="tsm" runat="server" />
Instead of .TargetControlID = targetDDL.ID I needed to use:
.TargetControlID = targetDDL.UniqueId

Resources