Comparing variables to SQL / Troubleshooting session - asp.net

I am trying to send some variables, using a session, to the next page "ProcedureSelectionForm.aspx". As you can see, the sessions have been commented out. The code below will work (without sending the variable of course). However, when you remove the comments the .onclick function reloads the page rather than navigating to "ProcedureSelectionForm.aspx". For this reason, I believe this is where my problem is. The first two columns are "Account" and "Password" in the database. I have not misspelled anything. I am new to VB and ASP.net and would appreciate some explanation as to what is happening and why my desired functionality isn't materializing. Thank you for your help!
If IsValid Then
Try
Dim strSQL = "select * from CreatePatient where Account = #Account and Password = #Password"
Using CCSQL = New SqlConnection(ConfigurationManager.ConnectionStrings("CreatePatientConnectionString").ConnectionString)
Using CCUser = New SqlCommand(strSQL, CCSQL)
CCSQL.Open()
CCUser.Parameters.Add("#Account", Data.SqlDbType.VarChar).Value = PatientAccount.Text
CCUser.Parameters.Add("#Password", Data.SqlDbType.VarChar).Value = PatientPass.Text
CCUser.ExecuteNonQuery()
'Using reader As SqlDataReader = CCUser.ExecuteReader()
'If reader.HasRows Then
'reader.Read()
'Session("user") = reader("Account")
'Session("pass") = reader("Password")
Response.Redirect("ProcedureSelectionForm.aspx")
'End If
'End Using
End Using
End Using
Catch ex As Exception
Label1.Text = ex.Message
End Try
End If

My friend was able to make time to help me out. I am unsure of what he did differently besides closing connections
If IsValid Then
Dim CCSQL As New SqlConnection
Dim CCUser As New SqlCommand
Dim strSQL As String
Dim dtrUser As SqlDataReader
Try
CCSQL.ConnectionString = ConfigurationManager.ConnectionStrings("CreatePatientConnectionString").ConnectionString
strSQL = "Select * from CreatePatient where Account=#user and Password=#pwd"
CCUser.CommandType = Data.CommandType.Text
CCUser.CommandText = strSQL
CCUser.Parameters.Add("#user", Data.SqlDbType.VarChar).Value = PatientAccount.Text
CCUser.Parameters.Add("#pwd", Data.SqlDbType.VarChar).Value = PatientPass.Text
CCSQL.Open()
CCUser.Connection = CCSQL
dtrUser = CCUser.ExecuteReader()
If dtrUser.HasRows Then
dtrUser.Read()
Session("user") = dtrUser("Account")
Session("level") = dtrUser("Password")
Response.Redirect("ProcedureSelectionForm.aspx")
Else
Label1.Text = "Please check your user name and password"
End If
dtrUser.Close()
CCSQL.Close()
Catch ex As Exception
Label1.Text = ex.Message
End Try
End If
I am on a tight deadline but i will get back to those interested with an answer. Thank you for your effort.

You don't want to do .ExecuteNonQuery() when you are actually doing a query (i.e. a SQL "SELECT" statement. You can just do the .ExecuteReader() to read those two values.
Also, I presume you are trying to validate the Account and Password; otherwise you could just set Session("user") = PatientAccount.Text and set Session("pass") = PatientPass.Text.

Related

Execute Scalar to Label. Subquery returned more than 1 value

So I have a label which shows the username of the user. I've used this value to return their ID which I then attach to a label. I used execute scalar to do this because I wasn't sure how else to get a single value on a label.
This works fine. I then use the ID from the label and put it in another table. I can do this twice and then the page crashes saying...
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
However I don't understand. I don't pull anything from the second table on the page. I don't know why it would affect it. I feel like I've tried everything. Taking out the line that posts the ID to the label lets the page run but I need it there.
Label2.Text = User.Identity.Name
Dim connetionString As String
Dim cnn As SqlConnection
Dim cmd As SqlCommand
Dim sql As String
connetionString = "Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\FYPMS_DB.mdf;Integrated Security=True"
sql = "SELECT SupID FROM Supervisor WHERE (Email = #Email)"
cnn = New SqlConnection(connetionString)
Try
cnn.Open()
cmd = New SqlCommand(sql, cnn)
cmd.Parameters.Add(New SqlParameter("#Email", User.Identity.Name))
Dim supid1 As Int32 = Convert.ToInt32(cmd.ExecuteScalar())
cmd.Dispose()
cnn.Close()
Label1.Text = supid1.ToString
Catch ex As Exception
MsgBox("Can not open connection ! ")
End Try
End Sub
This should return the first result for you. Also, it's a good idea to employ Using blocks for objects such as connections, commands, and readers.
Using cn = New SqlConnection("Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\FYPMS_DB.mdf;Integrated Security=True")
cn.Open()
Using cmd = New SqlCommand("SELECT SupID FROM Supervisor WHERE Email = #Email", cn)
cmd.Parameters.AddWithValue("#Email", User.Identity.Name)
Using dr = cmd.ExecuteReader
If dr.Read Then
Label1.Text = CInt(dr("SupID"))
End If
End Using
End Using
End Using
If you are not sure there are multiple rows for same email in that table, you can change the query to following, that will work for you with executescalar.
SELECT TOP 1 SupID FROM Supervisor WHERE (Email = #Email)
Horribly sorry! But yes you were right! There was another query going on in the background that I never noticed that was affecting it all. So sorry

ASP.NET VB.NET -- SQL UPDATE Command Not Working

I have been working on this particular issue for a couple of days, and scouring over SO, MSDN and other google searches has not proven to be of any use. I am trying to make a simple update to a SQL table. My SELECT and INSERT statements all work fine, but for some reason, this update will not work. I have set breakpoints and stepped through, and the code seems to be working fine -- the Catch ex as Exception is never reached after the .ExecuteNonQuery() fires off.
Could anyone give me an idea of why I've been unable to get a SQL update?
Protected Sub SaveButton_Click(sender As Object, e As EventArgs) Handles SaveButton.Click
Dim currentUser = Membership.GetUser(User.Identity.Name)
Dim username As String = currentUser.UserName
Dim userId As Guid = currentUser.ProviderUserKey
UserNameTextBox.Text = username
' Get Root Web Config Connection String so you don't have to encrypt it
Dim rootWebConfig As System.Configuration.Configuration
rootWebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/")
Dim connString As System.Configuration.ConnectionStringSettings
connString = rootWebConfig.ConnectionStrings.ConnectionStrings("LocalSqlServer")
Dim conn As String = connString.ToString
Dim commandString As String = "UPDATE UserDetails SET FirstName ='" + FirstNameTextBox.Text + "' WHERE UserId ='" + userId.ToString + "'"
Dim fname As String = FirstNameTextBox.Text
Dim commandText As String = "UPDATE UserDetails SET FirstName=#firstname WHERE UserId=#UID;"
Using connection As New SqlConnection(conn)
Dim command As New SqlCommand(commandText, connection)
command.CommandType = CommandType.Text
' Add UserId parameter for WHERE clause.
command.Parameters.Add("#UID", SqlDbType.UniqueIdentifier).Value = userId
' command.Parameters("#UID").Value = userId
' command.Parameters.AddWithValue("#UID", userId)
' Use AddWithValue to assign Demographics.
command.Parameters.Add("#firstname", SqlDbType.VarChar, 255).Value = fname
'command.Parameters.AddWithValue("#firstname", fname)
' command.Parameters("#firstname").Value = FirstNameTextBox.Text.ToString
Try
connection.Open()
command.ExecuteNonQuery()
Dim rowsAffected As Integer = command.ExecuteNonQuery()
Console.WriteLine("RowsAffected: {0}", rowsAffected)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
connection.Close()
End Try
End Using
End Sub
You're running "command.ExecuteNonQuery()" twice, meaning the second execution will likely return 0 rows affected since you already updated what you needed to update, and that's what you're assigning to rowsAffected. Are you sure the UPDATE isn't occurring?
Edit: Re your comment, did you check for IsPostBack when you LoadUser? If not, when you click SaveButton, you're going to reload the existing values, and then you'll be updating with those existing values.

My code isn't giving the user's the correct feedback. Any ideas how to fix this?

I have a very simple code that invokes a stored procedure. The stored proc is used for sending out reminders to user's on expiring account.
When a user enters correct email address, the user gets a reminder email with the message, "Reminder sent successfully"
This is exactly what we want.
However, if the user enters an invalid email address, the user still sees same message, "Reminder sent successfully"
This is not good.
Can you please help with what I am doing wrong?
Please see entire (actual) code below:
Protected Sub BtnSubmit_Click(ByVal sender As System.Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles BtnSubmit.Click
Dim oConnection As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("sConnectionString").ConnectionString)
Dim oCommand As SqlCommand = New SqlCommand()
Try
oConnection.Open()
oCommand.Connection = oConnection
oCommand.CommandText = "AcountExpiration"
oCommand.CommandType = CommandType.StoredProcedure
oCommand.Parameters.Add(New SqlParameter("#Email", Data.SqlDbType.VarChar, 50)).Value = Email.Text
Dim adpt As New SqlDataAdapter(oCommand)
Dim ds As New DataSet()
adpt.Fill(ds)
oCommand.ExecuteReader()
lblMsg.Text="Reminder successfully sent"
Catch ex As SqlException
Response.Write("<SCRIPT LANGUAGE='JavaScript'>alert('" + ex.Message + "')</SCRIPT>")
Finally
oConnection.Close()
End Try
End Sub
c# solution is welcome as well.
Dim scmd As SqlCommand = New SqlCommand("AcountExpiration", Conn)
scmd.CommandType = CommandType.StoredProcedure
scmd.Parameters.AddWithValue("#Email", Email.Text)
'Dim r As SqlDataReader = scmd.ExecuteReader()
Dim validEmail As Boolean = False
Dim reader As SqlDataReader = scmd.ExecuteReader()
While reader.Read()
'if we are here then something got returned.
'so probably a valid email.
validEmail = True
End While
If validEmail = True Then
lblMsg.Text = "Success"
Else
lblMsg.Text = "email does not exit on our system"
End If
You have a couple of different options as I see it.
Have the sproc throw an error if the email address isn't valid.
Have validation on the dataset to check and make sure you are getting back the expected values. Only display the success message if there was actually a success.
I would not use a SqlDataAdapter or Dataset for this. just use the SqlDataReader
bool validEmail = false;
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//if we are here then something got returned.
//so probably a valid email.
validEmail = true;
}
Or use ExecuteScalar
bool validEmail = Convert.ToBoolean(command.ExecuteScalar());
then
if(validEmail)
{
}
else
{
}
UPDATE
Will add an update for this as some people don't realise that certain code wont magically work. I have already included links for ExecuteScalar and ExecuteReader to show how to use these methods.
If you wanted to use ExecuteScalar you would have to change your stored procedure to return a value that could then be parsed as a Boolean.
The above methods is simply for checking if an email exists in the DB. No this does not valdate an email address, as I would expect that to occur before this code would be reached.

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.

ASP.NET - Could not find stored procedure

I've been searching the depths of the internet and all the solutions I found did not solve this problem.
I am using Visual Web Developer 2010 Express with SQL Server 2008, using VB.
I am trying to execute a stored procedure to insert some data coming from a textbox control to a database, if the id doesn't exist it inserts both the id given in the textbox and the current date (time_scanned_in), if the id exists already, it will insert the current datetime in the [time_scanned_out] column, if all 3 fields in the db are full, it will return #message = 1.
Here is the sql stored procedure:
ALTER PROCEDURE dbo.InsertDateTime
#barcode_id nchar(20),
#message char(1) = 0 Output
AS
BEGIN
if not exists(select * from tblWork where barcode_id = #barcode_id)
begin
INSERT INTO [tblWork] ([barcode_id], [time_scanned]) VALUES (#barcode_id, GetDate())
end
else if exists(select * from tblWork where barcode_id = #barcode_id AND time_scanned_out IS NOT NULL )
begin
SET #message=1
end
else if exists(select * from tblWork where barcode_id = #barcode_id AND time_scanned_out IS NULL)
begin
UPDATE [tblWork] SET [time_scanned_out] = GetDate() WHERE [barcode_id] = #barcode_id
end
RETURN #message
end
If I execute this (by right clicking on the SP), it works flawlessly and returns the values when all fields have been filled.
But when executed through the vb code, no such procedure can be found, giving the error in the title.
Here is the vb code:
Dim opconn As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"
Dim sqlConnection1 As New SqlConnection(opconn)
Dim cmd As New SqlCommand
Dim returnValue As Object
cmd.CommandText = "InsertDateTime"
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = sqlConnection1
sqlConnection1.Open()
With cmd.Parameters.Add(New SqlParameter("#barcode_id", TextBox.Text))
End With
With cmd.Parameters.Add(New SqlParameter("#message", SqlDbType.Char, 1, Label3.Text))
End With
returnValue = cmd.ExecuteScalar()
sqlConnection1.Close()
Note, I haven't done the code for the return part yet, will do that once I get it to locate the SP.
Tried listing all objects with the sys.objects.name for each of the databases in a gridview, it listed everything but the stored procedure I want.
Why is this, any ideas? Would be much appreciated, spent hours trying to find a solution.
If anyone needs any more code or information feel free to ask.
try cmd.parameters.clear() first and then start adding parameters in cmd object. also instead of cmd.executescaler(), try cmd.executenonquery or cmd.executeReader()
Try this
cmd.Parameters.AddWithValue("#barcode_id", TextBox.Text)
SqlParameter prmOut = cmd.Parameters.Add("#message",SqlDbType.Char, 1)
prmOut.Value = Label3.Text
prmOut.Direction = ParameterDirection.InputOutput
cmd.ExecuteNonQuery()
returnValue = prmOut.Value.ToString()
Recreated the whole project with a whole new database, copied all the same code, and now it all works flawlessly! Still have no idea what was wrong, but thank you all, you were all prompt and knowledgable.
Here was the final VB code for anyone who's interested:
Dim myConnection As New SqlConnection(opconn)
Dim cmd As New SqlCommand()
Dim myReader As SqlDataReader
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = myConnection
cmd.CommandText = "InsertTimes"
cmd.Parameters.AddWithValue("#message", OleDbType.Integer)
cmd.Parameters.AddWithValue("#barcode_id", TextBox.Text)
cmd.Parameters("#message").Direction = ParameterDirection.Output
Try
myConnection.Open()
myReader = cmd.ExecuteReader()
Dim returnMessage As String = cmd.Parameters("#message").Value
If returnMessage = 1 Then
label_confirmation.Text = "Record successfully submitted!"
TextBox.Text = ""
ElseIf returnMessage = 2 Then
label_confirmation.Text = "A finish time already exists for the record '" & TextBox.Text & "', would you like to override the finish time anyway?"
button_yes.Visible = True
button_no.Visible = True
ElseIf returnMessage = 3 Then
label_confirmation.Text = "Record submitted, work operation status complete!"
TextBox.Text = ""
End If
Catch ex As Exception
label_confirmation.Text = ex.ToString()
Finally
myConnection.Close()
End Try

Resources