An example of advanced database search - asp.net

im looking for an example script. I saw one yesterday but for the life of me I can't find it again today.
The task I have is to allow the user to search 1 database table via input controls on an aspx page where they can select and , or , equals to combine fields, generating the sql on the fly with concat/stringbuilder or similar. (it runs behind the corp firewall)
Please can someone point me in the right direction of an example or tutorial
I've been working on the page, but have run into problems. Here is the Page_load;
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim sql As String = ("Select * From Table Where ")
'variables to hold the and or values between fields
Dim andor1v As String = AndOr1.SelectedValue.ToString()
Dim andor2v As String = AndOr2.SelectedValue.ToString()
Dim andor3v As String = AndOr3.SelectedValue.ToString()
Dim andor4v As String = AndOr4.SelectedValue.ToString()
Dim andor5v As String = AndOr5.SelectedValue.ToString()
Dim andor6v As String = AndOr6.SelectedValue.ToString()
'variables to stop web control inputs going direct to sql
Dim name As String = NameSearch.Text.ToString()
Dim email As String = EmailSearch.Text.ToString()
Dim city As String = CitySearchBox.Text.ToString()
Dim province As String = ProvinceSelect.SelectedValue.ToString()
Dim qualifications As String = QualificationsObtained.Text.ToString()
Dim competencies As String = CompetenciesDD.SelectedValue.ToString()
Dim expertise As String = Expertiselist.SelectedValue.ToString()
If NameSearch.Text IsNot String.Empty Then
sql += "Surname LIKE '%" & name & "%' "
End If
If EmailSearch.Text IsNot String.Empty Then
sql += andor1v & " Email LIKE '%" & email & "%' "
End If
If CitySearchBox.Text IsNot String.Empty Then
sql += andor2v & " City LIKE '%" & city & "%' "
End If
If QualificationsObtained.Text IsNot String.Empty Then
sql += andor3v & " (institutionquals1 LIKE '%" & qualifications & "%') OR " & _
"(institutionquals2 LIKE '%" & qualifications & "%') OR " & _
"(institutionquals3 LIKE '%" & qualifications & "%') OR " & _
"(institutionquals4 LIKE '%" & qualifications & "%') "
End If
Dim selectedrow As String = CompetenciesDD.SelectedValue.ToString
Dim selectedquals As String = NQFlevel.SelectedValue.ToString
If CompetenciesDD.SelectedValue.ToString IsNot "0" And selectedquals = 0 Then
sql += (selectedrow & " = 1 ")
ElseIf selectedrow = "assessortrue" And selectedquals IsNot "0" Then
sql += andor4v & (" assessortrue=1 and assessorlvl=" & selectedquals)
ElseIf selectedrow = "coordinatortrue" And selectedquals IsNot "0" Then
sql += andor4v & ("coordinatortrue=1 and coordinatorlvl=" & selectedquals)
ElseIf selectedrow = "facilitatortrue" And selectedquals IsNot "0" Then
sql += andor4v & ("facilitatortrue=1 and facilitatorlvl=" & selectedquals)
ElseIf selectedrow = "moderatortrue" And selectedquals IsNot "0" Then
sql += andor4v & ("moderatortrue=1 and moderatorlvl=" & selectedquals)
ElseIf selectedrow = "productdevelopertrue" And selectedquals IsNot "0" Then
sql += andor4v & ("productdevelopertrue=1 and productdeveloperlvl=" & selectedquals)
ElseIf selectedrow = "projectmanagertrue" And selectedquals IsNot "0" Then
sql += andor4v & ("projectmanagertrue=1 and projectmanagerlvl=" & selectedquals)
End If
Response.Write(sql)
End Sub
After an hours tinkering the code is now looking as it does above ^
Now the problem im faced with is if a user does not enter a value for surname (the first field) but does enter a value for email (or any subsequent fields), the sql produced has an extra and like this;
Select * From Table Where And Email LIKE '%test%'
I'm also looking for a way to take the OR option into account. Do you think this should be done as Martin says where the whole query is either an and or an or and not a mix of the 2? Then I should be able to take out all the and/or drop downs?
Thanks.
NB: I'm not really looking for comments on how I should parameterise or about sql injection.

Regarding your issue with users not selecting an option you could just remove the "please select" and have it default to "and"
Also what is the desired behaviour if they select a mix of ANDs and ORs?
By default the ANDs will be evaluated first in the absence of any brackets
http://msdn.microsoft.com/en-us/library/ms186992.aspx
So if they enter
name="Fred" or email="blah" and
city="london" and province="xyz" or
qualifications="Degree"
I'm not really sure what the desired semantics would be?
Is it
(name="Fred" or email="blah") and
city="london" and (province="xyz" or
qualifications="Degree")
or
(name="Fred" or (email="blah" and
city="london") and province="xyz") or
qualifications="Degree"
Or something different? Maybe you should restrict them to AND or OR for the whole query or allow them to disambiguate either by typing in advanced search syntax with brackets or by providing a query builder UI.

To avoid sql injection and allow a dynamic search I would probably write a stored procedure something like this. If nothing is selected send DBNull.Value in the ado.net parameters collection as the parameter value. With this approach you can check any columns you want and if they are not selected by the user they will be ignored.
EDIT: I just saw that you are not allowed to use stored procedures. I changed my answer below to show a parameterized sql statement
SELECT * FROM TABLE
WHERE ([name] = #name OR #name IS NULL)
AND (email = #email OR #email IS NULL)
AND (city = #city OR #city IS NULL)
AND (province = #province OR #province IS NULL)
AND (qualifications = #qualifications OR #qualifications IS NULL)
AND (competencies = #competencies OR #competencies IS NULL)
AND (expertise = #expertise OR #expertise IS NULL)

Concat strings to build a query is never a good idea. You should use a stored procedure or parametrized queries

I have done this "dynamic" type query interface on classic asp.
The advice that I give to you is that you are trying to do the whole query in one page load so...
Look to "building" the query via a "wizard" type interface - either ajax for the newness or simple multiple pages for each part of the query building.
This is essence gives you "persitance" via what ever means you have (session, dbstore, cookie etc) for each part of the query and you have can sanity check each part of the query as you build.

Dim sql As String = ("Select * From Table Where **1=1**")
'variables to hold the and or values between fields
Dim andor1v As String = AndOr1.SelectedValue.ToString()
Dim andor2v As String = AndOr2.SelectedValue.ToString()
Dim andor3v As String = AndOr3.SelectedValue.ToString()
Dim andor4v As String = AndOr4.SelectedValue.ToString()
Dim andor5v As String = AndOr5.SelectedValue.ToString()
Dim andor6v As String = AndOr6.SelectedValue.ToString()
'variables to stop web control inputs going direct to sql
Dim name As String = NameSearch.Text.ToString()
Dim email As String = EmailSearch.Text.ToString()
Dim city As String = CitySearchBox.Text.ToString()
Dim province As String = ProvinceSelect.SelectedValue.ToString()
Dim qualifications As String = QualificationsObtained.Text.ToString()
Dim competencies As String = CompetenciesDD.SelectedValue.ToString()
Dim expertise As String = Expertiselist.SelectedValue.ToString()
If NameSearch.Text IsNot String.Empty And andor1v IsNot "0" Then
sql += "**and** Surname LIKE '%" & name & "%' "
ElseIf NameSearch.Text IsNot String.Empty And andor1v Is "0" Then
sql += "**or** Surname LIKE '%" & name & "%' "
End If
....additional logic here.....
Response.Write(sql)
End Sub
note the ** parts. 1=1 evaluates to true on most DBMS. This allows you to just start concatenating your or / ands on to it without worrying about ()'s

Related

JSON.net - Using VB.NET Unable to iterate through results

I am trying to process this json document using JSON.NET.
With the VB.NET code:
Dim o As JObject = JObject.Parse(json)
Dim results As List(Of JToken) = o.Children().ToList
Dim count As Integer = 0
For Each item As JProperty In results
Dim snippet As String = String.Empty
Dim URL As String = String.Empty
Dim source As String = String.Empty
item.CreateReader()
Select Case item.Name
Case "response"
snippet = item.Last.SelectToken("docs").First.Item("snippet").ToString
URL = item.Last.SelectToken("docs").First.Item("web_url").ToString
source = ControlChars.NewLine & "<font size='2'>" & item.First.SelectToken("docs").First.Item("source").ToString & "</font>" & ControlChars.NewLine
tbNews.Text &= "<a href=" & URL & " target='new'>" & snippet & "</a> - " & source
End Select
Next
I am only receiving the first document as a result. Can someone advise as to how I can get the 1st - Nth documents as a complete list?
The docs are 2 levels deep, you're only looping in the top level. Try this...
Dim parsedObject = JObject.Parse(json)
Dim docs = parsedObject("response")("docs")
For Each doc In docs
Dim snippet As String = doc("snippet")
Dim URL As String = doc("web_url")
Dim source As String = doc("source")
'....
Next

Access and SQL date comparison

I have an Access 2010 front and sql2008 back. I am using a date parameter on a form and a view for the report. It doesn't give me any data. It's not understanding the access date paramter. I have tried converting the date in sql, but still no data. Here is the code I am using.
Private Sub Report_Open(Cancel As Integer)
LocationRpt
End Sub
Private Sub LocationRpt()
Dim frm As Form_frmSecRpt
Dim strSQL As String
Dim SchDt As Date
Set frm = Form_frmSecRpt
SchDt = frm.txtDate
strSQL = "Select * From vw_SecLocationWO Where ReSchDt =" & SchDt
Me.RecordSource = strSQL
End Sub
Access SQL expects date values to be delimited with hash marks (#), so try this instead:
strSQL = "SELECT * FROM vw_SecLocationWO WHERE ReSchDt = #" & Format(SchDt, "yyyy-mm-dd") & "#"

second ExecuteReader() doesn't work

I have a code which checks the validity of user and then, if a user is valid it inserts certain values in the database.
My problem is when After I query my database to check if a user is valid and after that i try to pass the additional value to its account the flow stops when I invoke ExecuteReader() for the second time.
There is no error, or anything like that. I tried to substitute ExecuteReader() with ExecuteNoneQuery but still it's not working. I tried all the query in mysql command prompt they are working perfectly. I really can't understand what am I doing wrong there. Can anyone help me please?
Here is the code:
Try
myconn.Open()
Dim stquery As String = "SELECT * from accountstbl WHERE SE_ID = " & Id.Text
Dim smd = New MySqlCommand(stquery, myconn)
Dim myreader = smd.ExecuteReader()
If Not myreader.HasRows Then
errorUser.Visible = True
Else
myreader.Read()
Dim name As String = myreader.Item("user_name").ToString()
Dim stquery2 = "INSERT into backup VALUES (" & name & ", '" & Info & "')"
Dim smd2 = New MySqlCommand(stquery2, myconn)
Dim Myreader2 As MySqlDataReader
'smd.ExecuteNonQuery()'
'THE CODE STOPS HERE'
Myreader2 = smd2.ExecuteReader()
'Myreader2.Read()'
MsgBox("The BACKUP INFORMATION HAS BEEN SAVED")
End If
myconn.Close()
Catch ex As Exception
Dim ErrorMessage As String = "alert('" & ex.Message.ToString() & "');"
Page.ClientScript.RegisterStartupScript(Me.GetType(), "ErrorAlert", ErrorMessage, True)
myconn.Close()
End Try
Because your second query is an update, not a select, you need to execute it using the ExecuteNonQuery method. Your commented-out code shows an attempt to call ExecuteNonQuery but on the wrong command object (smd when it should be smd2). Try something like this instead:
myreader.Read()
Dim name As String = myreader.Item("user_name").ToString()
Dim stquery2 = "INSERT into backup VALUES (" & name & ", '" & Info & "')"
Dim smd2 = New MySqlCommand(stquery2, myconn)
smd2.ExecuteNonQuery()
The ExecuteNonQuery method returns the number of rows updated as an int value, so you can capture it if it's valuable to you. In your case it's probably not, but here's how you'd check anyway:
int rowsAdded = smd2.ExecuteNonQuery();
if (rowsAdded == 1) {
// expected this
} else {
// didn't expect this
}
Finally, concatenating strings to build SQL commands can leave you vulnerable to SQL Injection attacks. Please take a look at using parameterized queries. There's a decent example here.
If you want to execute nested Reader, you have to create another connection. You need somethig like
smd2 = New MySqlCommand(stquery2, myconn2)' myconn2 is another connection
OR
Set "MultipleActiveResultSets=True in your connection string.
Also, use ExecuteNonQuery() for Inserting
Dim name As String = myreader("user_name").ToString()
Dim stquery2 = "INSERT into backup VALUES ('" & name & "', '" & Info & "')"
Dim smd2 = New MySqlCommand(stquery2, myconn)
smd.ExecuteNonQuery()
Please use Parameterized query to avoid SQL Injection
The logic is that you need to close your first reader (myreader) before executing another reader (MyReader2) on the same connection.

How do I make this asp.net email go to a database?

I ave a contact form (VS 2010 / VB / .net4), and when the client fills out the form, I get an email -- which I like, but ....
For instance, here's an e-mail I got:
Email: ivy_league_alum-at-yahoo.com
Subject: Do you guys integrate PPT?
Message: I'm looking for a PPT integrator in the Michigan area.
First_Name: Tim
Last_Name: Dewar
Organization: American Axle
Browser: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like
Gecko) Chrome/16.0.912.75 Safari/535.7
IP Address: 184.60.79.96
Server Date & Time: 1/13/2012 11:28:59 AM
This is just a lead-generating company, so we're gonna get a lot of emails and we're gonna want them organized.
It was suggested by Jon P that I use a database to gather all these emails I'm getting, instead of MS Excel (which I wouldn't know how to do anyway). So I downloaded SQL Server Express. So now what do I do? Can someone please tell me what I have to add to the code, specifically, or what I have to do, so I can gather these emails in an organized manner? Thanks!
Addendum (I know this is long):
Specifically, my email code is:
<%# Page Title="Contact Health Nutts" Language="VB"
MasterPageFile="~/Site.master" AutoEventWireup="false"
CodeFile="contact.aspx.vb" Inherits="contact" %>
Protected Sub SubmitForm_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If Not Page.IsValid Then Exit Sub
Dim SendResultsTo As String = "jason.weber-at-healthynutts.com"
Dim smtpMailServer As String = "smtp.healthynutts.com"
Dim smtpUsername As String = "jason.weber-at-healthynutts.com"
Dim smtpPassword As String = "********"
Dim MailSubject As String = "Form Results"
Try
Dim txtQ As TextBox = Me.FormContent.FindControl("TextBoxQ")
If txtQ IsNot Nothing Then
Dim ans As String = ViewState("hf1")
If ans.ToLower <> txtQ.Text.ToLower Or ans.ToUpper <> txtQ.Text.ToUpper Then
Me.YourForm.ActiveViewIndex = 3
Exit Sub
End If
End If
Dim FromEmail As String = SendResultsTo
Dim msgBody As StringBuilder = New StringBuilder()
Dim sendCC As Boolean = False
For Each c As Control In Me.FormContent.Controls
Select Case c.GetType.ToString
Case "System.Web.UI.WebControls.TextBox"
Dim txt As TextBox = CType(c, TextBox)
If txt.ID.ToLower <> "textboxq" Then
msgBody.Append(txt.ID & ": " & txt.Text & vbCrLf & vbCrLf)
End If
If txt.ID.ToLower = "email" Then
FromEmail = txt.Text
End If
If txt.ID.ToLower = "subject" Then
MailSubject = txt.Text
End If
Case "System.Web.UI.WebControls.CheckBox"
Dim chk As CheckBox = CType(c, CheckBox)
If chk.ID.ToLower = "checkboxcc" Then
If chk.Checked Then sendCC = True
Else
msgBody.Append(chk.ID & ": " & chk.Checked & vbCrLf & vbCrLf)
End If
Case "System.Web.UI.WebControls.RadioButton"
Dim rad As RadioButton = CType(c, RadioButton)
msgBody.Append(rad.ID & ": " & rad.Checked & vbCrLf & vbCrLf)
Case "System.Web.UI.WebControls.DropDownList"
Dim ddl As DropDownList = CType(c, DropDownList)
msgBody.Append(ddl.ID & ": " & ddl.SelectedValue & vbCrLf & vbCrLf)
End Select
Next
msgBody.AppendLine()
msgBody.Append("Browser: " & Request.UserAgent & vbCrLf & vbCrLf)
msgBody.Append("IP Address: " & Request.UserHostAddress & vbCrLf & vbCrLf)
msgBody.Append("Server Date & Time: " & DateTime.Now & vbCrLf & vbCrLf)
Dim myMessage As System.Net.Mail.MailMessage = New System.Net.Mail.MailMessage()
myMessage.To.Add(SendResultsTo)
myMessage.From = New System.Net.Mail.MailAddress(FromEmail)
myMessage.Subject = MailSubject
myMessage.Body = msgBody.ToString
myMessage.IsBodyHtml = False
If sendCC Then myMessage.CC.Add(FromEmail)
Dim basicAuthenticationInfo As New System.Net.NetworkCredential(smtpUsername, smtpPassword)
Dim MailObj As New System.Net.Mail.SmtpClient(smtpMailServer)
MailObj.Credentials = basicAuthenticationInfo
MailObj.Send(myMessage)
Me.YourForm.ActiveViewIndex = 1
Catch
Me.YourForm.ActiveViewIndex = 2
End Try
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If Not Page.IsPostBack Then
Dim lbl As Label = Me.FormContent.FindControl("labelq")
If lbl IsNot Nothing Then
Dim rq(3) As String
rq(0) = "Is fire hot or cold?"
rq(1) = "Is ice hot or cold?"
rq(2) = "Is water wet or dry?"
Dim ra(3) As String
ra(0) = "hot"
ra(1) = "cold"
ra(2) = "wet"
Dim rnd As New Random
Dim rn As Integer = rnd.Next(0, 3)
lbl.Text = rq(rn)
ViewState("hf1") = ra(rn)
End If
End If
End Sub
</script> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> <h1>CONTACT HEALTH
NUTTS AND WORK FROM THE COMFORT OF YOUR OWN HOME!
Enter your Email Address:
* Required
* Please enter a valid email address.
Subject:
* Required
Please type your message below:
* Required
First Name:
* Required
Last Name:
* Required
Phone Number:
* Required
* Please enter a valid U.S. phone number (including dashes).
City:
* Required
State/Province:
* Required
Your message has been sent. Thank you for contacting us.
Due to technical difficulty, your message may NOT have been sent.
You did not correctly answer the anti-spam question. Please go back and try again.
Don't take this the wrong way, but judging by what you've said about your lack of coding abilities, it may work out cheaper for you to get someone else to do the work for you. A competent coder should be able to knock something out for you in about an hour, probably less if he doesn't stop for coffee.
If you do really really want to do it yourself, then first off, you're going to have to find out if the hosting packing for the website includes a database or not.
Assuming you don't host the website on your local machine, then having a version of SQL Express on your machine will help you develop the code, but you won't be able to deploy it.
Completely ignoring that though, steps you want to go through are:
Create the database in SQL, then create the relevant database
table
Create a connection from the website to the database using ADO.Net
Create the code to insert the contact form data into the database table
You then need to think about how you're going to view the data once it's been collected, so you're either going to have to write something or learn SQL.
If you want some code samples to help you get going, then we need to know what language you're using (it should be C# or VB.Net) and posting the code for the contact form would help as well (obviously deleting any sensitive details, such as usernames and passwords).
EDIT:
Once you've created the database, this script should give you a basic table structure in SQL Express:
CREATE TABLE [dbo].[tblEmails](
[EmailID] [int] IDENTITY(1,1) NOT NULL,
[EmailAddress] [nvarchar](200) NOT NULL,
[Subject] [nvarchar](200) NOT NULL,
[Message] [nvarchar](max) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[PhoneNumber] [nvarchar](20) NOT NULL,
[City] [nvarchar](50) NOT NULL,
[State] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_tblEmails2] PRIMARY KEY CLUSTERED
(
[EmailID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
To use it, right click on the database in SQL Express, click New Query, paste the above into the window, then hit the Execute button, refresh the database and you shouldn't see the table.
Here is a good tutorial if you're using ajax too.
http://dotnetslackers.com/articles/aspnet/Developing-an-AJAX-and-ASP-NET-4-0-Based-Online-E-mail-System-Part1.aspx

Writing an update query in asp.net (access database) (visual basic)

I have this code:
Dim pathString As String = HttpContext.Current.Request.MapPath("Banking.mdb")
Dim odbconBanking As New OleDbConnection _
("Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" + pathString)
Dim sql As String
sql = "UPDATE tblAccounts balance = " & CDbl(balance + value) & " WHERE(accountID = " & accountID & ")"
odbconBanking.Open()
Dim cmd As New OleDbCommand(sql, odbconBanking)
cmd.ExecuteNonQuery()
However, an exception is thrown, when I run it:
Syntax error in UPDATE statement.
I tried to run a similar statement in Access and it works fine.
I think the missing is SET.
Try: UPDATE table SET field = newvalue WHERE criteria;
Just modify:
sql = "UPDATE tblAccounts SET balance = " & CDbl(balance + value) & " WHERE(accountID = " & accountID & ")"
http://office.microsoft.com/en-us/access/HA100765271033.aspx
The SQL Statement definitely is missing the SET keyword. Also, I suggest you to brush up on parameterized query:
Dim sql As String = "UPDATE tblAccounts " & _
"SET balance = ? " & _
"WHERE(accountID = ?)"
Dim cmd As New OleDbCommand(sql, odbconBanking)
cmd.Parameters.Add("Balance", CDbl(balance + value))
cmd.Parameters.Add("AccountId", accountID
cmd.ExecuteNonQuery()
This way, not only is the SQL Statment is clearer, it help prevents possible SQL injection attacks.
You are missing SET as part of UPDATE.
It should be UPDATE tablename SET fieldname = ... WHERE [criteria].
On a side note, you are using classic asp style code inside asp.net. I will suggest reading some docs on ASP.net and how to design applications in a layered manner.
A good start is here: Enterprise Library's Data Access Application Block
Link: https://web.archive.org/web/20210612110113/https://aspnet.4guysfromrolla.com/articles/030905-1.aspx

Resources