UPDATE statement in asp.net doesn't do anything - asp.net

I am making a settings page on my website where the user can change his email adress, name, etc.
The problem is the update statement, it doesn't work, because nothing has changed in the database, but it doesn't give me an error, so I don't know what's up.
When I check with breakpoints it shows that the parameters are getting the right values, and when i search on the internet I can't find anyone with the same problem.
I will paste the code of the update below:
Dim CmdUpdate As New OleDbCommand
Dim Sqlstatement As String = "UPDATE tblUsers SET firstname = #firstname, lastname = #lastname, userPassword = #userPassword, email = #email, avatar = #avatar WHERE userID = #userID;"
CmdUpdate.Connection = dbConn.cn
CmdUpdate.CommandText = Sqlstatement
CmdUpdate.Parameters.AddWithValue("firstname", txtFirstName.Text)
CmdUpdate.Parameters.AddWithValue("lastname", txtLastName.Text)
CmdUpdate.Parameters.AddWithValue("userID", Session("userID"))
If txtPassword.Text = "" Then
CmdUpdate.Parameters.AddWithValue("userPassword", Session("hashedpass"))
Else
CmdUpdate.Parameters.AddWithValue("userPassword", hash(txtPassword.Text))
End If
CmdUpdate.Parameters.AddWithValue("email", txtEmail.Text)
CmdUpdate.Parameters.AddWithValue("avatar", strAvatar)
dbConn.cn.Close()
dbConn.cn.Open()
CmdUpdate.ExecuteNonQuery()
dbConn.cn.Close()

Is it possible that the userid column just doesn't match, so your WHERE clause matches zero records and nothing gets updated? That could be caused by a number of things -- whitespace, character encoding, and so forth.

You just have to include the "#" in your parameter add statements :
CmdUpdate.Parameters.AddWithValue("#firstname", txtFirstName.Text)
...and so on...

You missed the '#'s in the sql-parameters:
CmdUpdate.Parameters.AddWithValue("#firstname", txtFirstName.Text)
etc.

Use
CmdUpdate.Parameters.AddWithValue("#firstname", txtFirstName.Text)
You were missing to add '#' in AddWithValue()
See Tutorial here

Related

Stored Procedure not working from ASP.NET

I have the following stored procedure:
alter proc SPCP_ProgramUpdate
#ID int,
#UserID int,
#Name nvarchar(150),
#University int,
#Level tinyint,
#isActive bit
as
update tblUniversityProgram set University_Fkey = #University, Level_Fkey = #Level, Program_Name = #Name, EditDate = GETDATE(), EditUser = #UserID, isActive = #isActive
where tblUniversityProgram.ID = #ID
When I run the stored procedure from SSMS, it works as intended.
However, when I run that stored procedure from ASP.NET using this code:
Dim varDbconn As New SqlConnection
Dim varDbcomm As SqlCommand
Dim varDbRead As SqlDataReader
varDbconn.ConnectionString = ConfigurationManager.ConnectionStrings("CPDB_ConnectionString").ToString
varDbconn.Open()
If Request.QueryString("program") <> "" Then
varDbcomm = New SqlCommand("SPCP_ProgramUpdate", varDbconn)
varDbcomm.CommandType = CommandType.StoredProcedure
varDbcomm.Parameters.AddWithValue("#ID", Request.QueryString("program")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#UserID", Session("UserID")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#University", Session("DecryptID")).DbType = DbType.Int32
varDbcomm.Parameters.AddWithValue("#Level", ddlLevel.SelectedValue).DbType = DbType.Byte
varDbcomm.Parameters.AddWithValue("#isActive", chkisActive.Checked).DbType = DbType.Boolean
varDbcomm.Parameters.AddWithValue("#Name", txttitle.Text).DbType = DbType.String
varDbcomm.ExecuteNonQuery()
varDbcomm.Dispose()
Else
....
End IF
varDbconn.Close()
nothing happens.
Any ideas?
The most likely answer to your question is that the value you are getting out of the querystring for program is not the Id in your database that you expect.
At the minute, your code is reading in input values and passing them to a stored procedure without any validation of your expected values - missing session for example could cause you all sorts of unexpected issues.
Debug your code and see exactly what parameters you are passing to your DB. Check your connection string to see that you are hitting the database where you have amended your stored procedure.
What you have should work. I would use parmaters.Add in place of addwith, but that should not really matter.
Try adding this code right after you are done setting up the parmaters:
Debug.Print("SQL = " & varDbcomm.CommandText)
For Each p As SqlParameter In varDbcomm.Parameters
Debug.Print(p.ParameterName & "->" & p.Value)
Next
That way in the debug window (or immediate depending on VS settings), you see a list of param values, and the parameter names. I suspect one of the session() values is messed up here.

Redirecting a user to appropriate page is not redirecting correctly. Any ideas?

I understand that there are several resources on how to redirect a user to a specific page based on his or her access level.
My issue is that my has some flaws preventing it from working correctly.
Your assistance is greatly appreciated.
Here is what we are trying to do.
We have employees with grievances. These employees are provided with a link to access and file their grievances.
Once the employee has filed his/her grievance, then the employee's manager would then log in and will be redirected to a page that shows all employees who have filed grievances so they review their grievances and determine whether or not the employees are approved to meet a board to review their cases and this is where I am stuck.
There are two tables that I didn't design. So, I am trying to make the best of what I am handed.
One table, called Employee has employee username (employeeID) and password (ssn).
The other table called Details has employeeID (related to Employee table) and ManagerID also related to Employee table by EmployeeID
Once a user files his/her grievance and submits it, his/her manager's ID (EmployeeID) is saved to the details table as ManagerID.
The idea is that once a manager logs into the system and his/her ID (ManageID) is present in details table, s/he will be redirected to a page called Decision.aspx.
When I attempted coding it, everyone, including Managers are being redirected to the same page called LetterOfIntent.aspx.
Any ideas what I am doing wrong?
Code is below:
StrSQL = "Select Dept, division, divisionManager, EmployeeName,Employee.EmpID, Email, SSN,Category FROM Employee e,Details d Where e.empID = d.managerID OR e.empID = #empid and SSN=#Password"
' Initialize Database Connection
Dim connStr As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
Dim conn As New SqlConnection(connStr)
Dim cmd As New SqlCommand(StrSQL, conn)
'We use parametized query to prevent sql injection attack
Dim p1 As New SqlParameter("#enpid", StrUser)
Dim p2 As New SqlParameter("#Password", StrPass)
cmd.Parameters.Add(p1)
cmd.Parameters.Add(p2)
While dr.Read()
If dr("empid") <> "" And dr("ssn") <> "" Then
Session("fullname") = dr("empName")
Session("dept") = dr("Dept")
Session("password") = dr("SSN")
Session("Email") = dr("Email")
Session("division") = dr("division")
Session("empid") = dr("empid")
Session("managerID") = dr("managerId")
Session("Cat") = dr("Category")
BValid = True
Else
End If
End While
' This handles all response per validation
If BValid = True Then
If Session("Cat") = "Pending" Then
Response.Redirect("~/pending.aspx")
ElseIf Session("Cat") = "In Progress" Then
Response.Redirect("~/inprogress.aspx")
ElseIf Session("managerID") <> "" And Session("empid") = Session("managerID") Then '***This is a manager, send him/her to Decision page
Response.Redirect("~/Decision.aspx")
Else '***Ok, this is an employee trying to file grievance, send him to LetterofInternt page.
Response.Redirect("~/LetterOfIntent.aspx?myname= " & Session("empid") & "")
End If
'If all else fails, then reject their athentication attempt and let them know.
ElseIf BValid = False Then
lblMsg.ForeColor = Color.Red
lblMsg.Text = "Login failed. "
End If
I suspect that you need to ToString each of the values you're putting into session, like this:
Session("Cat") = dr("Category").ToString()
You'd need to put some null checking around each one but given the information it seems like its probably you're issue.

checking for duplicate values before attempting insert (ASP.NET)

I have a form where two fields on the first page of the form make up the primary key. I want to check for duplicate values before attempting to insert the record, since I don't want the user to go all the way through the form only to find out they can't submit it. So I'm trying to check for duplicate values when the user tries to go to the next page of the form. I wasn't quite sure how to do it, and sure enough I'm getting an error. ("Object reference not set to an instance of an object.") The problem is apparently in my if statement, "If myValue.Length > 0 Then", but I'm not sure what needs to be in place of that.
Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
'get values
Dim checkPrefix = txtCoursePrefix.Text
Dim checkNum = txtCourseNum.Text
'db connectivity
Dim myConn As New OleDbConnection
myConn.ConnectionString = AccessDataSource1.ConnectionString
myConn.Open()
'select records
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix='checkPrefix' AND course_number='checkNum'", myConn)
'execute(Command)
Dim myValue As String = mySelect.ExecuteScalar()
'check if record exists
If myValue.Length > 0 Then
CustomValidator1.ErrorMessage = "some exp text"
CustomValidator1.SetFocusOnError = "true"
CustomValidator1.IsValid = "false"
End If
End Sub
Thought I'd post the final solution:
'select records
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
'execute(Command)
Dim myValue = mySelect.ExecuteScalar()
'check if record exists
If myValue IsNot Nothing Then
CustomValidator1.SetFocusOnError = True
args.IsValid = False
End If
This error indicates that the content of myValue variable is null. If it's null you can't use Length property (or any other property for that matter) on it. You have to check for null explicitly:
If myValue IsNot Nothing Then
EDIT 1
Your sql query is wrong. I don't know what would be the right query, as I don't know your database, but I think you intender to write this:
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix=" + checfkPreix + " AND course_number=" + checkNum, myConn)
or something to that effect. You might want to consider using string.Format function for forming the string. And you also need to make sure that there is some kind of protection against SQL Injection, since you form your query from user input. In your case using of OleDbParameter might be appropriate.
Edit 2
You also right to mention that there might be a problem with ExecuteScalar. ExecuteScalar is supposed to return a single value and your select query are returning two (prefix and course_number). Change it so that it returns a single parameter SELECT prefix FROM or simply SELECT 1 FROM and then the rest of the query:
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
Edit 3
You are not setting failed validation properly in your validator.
Add
args.IsValid = False
inside your if statement.
First ExecuteScalar will only return a single value, so in this case you are only going to get the column prefix from the result. Second if there is no match with your query it will return null, so your next length check should account for that scenario:
if String.IsNullOrEmpty(myValue) Then
...
Reference: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
myValue is null if there is no duplicate, so you have to apply .Length only if myValue is not null (which means checking for null only is enough; without .Length)
If Not string.IsNullOrEmpty(myValue) Then
try something like this instead (you will have to adapt it to VB.Net) DBNull is different from Null or Nothing so you have to compare it to both
If myValue <> DBNull and not myvalue is nothing Then

How to get the insert ID from this ADODB.Recordset?

I'm trying to avoid using straight SQL queries in my web app. I looked around and have come to the conclusion that ADO Recordsets would be the best or at least safest tool for the job. I need to insert records into a database table. Unfortunately I'm at a loss as to how to get the identity value for the record which was just inserted. Here's a reduction of what I've got now:
<%
dim insertID, rs
set rs = Server.CreateObject("ADODB.Recordset")
rs.Open "my_table_name", conn, adOpenForwardOnly, adLockOptimistic
rs.AddNew()
Call m_map_values_to_rs(rs)
rs.Update()
insertID = rs("id")
rs.Close()
rs = Nothing
%>
The code I have is successfully inserting the record, but I can't for the life of me figure out how to get the id field of the Recordset to update after the insert. How can I get the identity column value back from this Recordset?
UPDATE - Here's the solution with regard to the code above.
I had to change the cursor type to adOpenKeyset instead of adOpenForwardOnly. After I did this the record is automatically updated with the "auto number" field's new value after the insert. However it is not what you think it is. The value of rs("id") doesn't become an integer or even a variant. It becomes some sort of Automation type and cannot be evaluated as a number. Nor can CInt() be used directly on that type for some reason. So what you must do is to convert the value to a string and then convert it to an Int. Here's how I managed that:
insertID = CInt( rs("id") & "" )
Thanks to Dee for their answer. It helped immensely.
This article explains the means of getting identity value with example code.
The relevant code snippet is:
<%
fakeValue = 5
set conn = CreateObject("ADODB.Connection")
conn.open "<conn string>"
sql = "INSERT someTable(IntColumn) values(" & fakeValue & ")" & _
VBCrLf & " SELECT ##IDENTITY"
set rs = conn.execute(sql)
response.write "New ID was " & rs(0)
rs.close: set rs = nothing
conn.close: set conn = nothing
%>

Compare values from data source to string

I'm just stumped on what to do with this code, I'm just trying to implement a 'no duplicates' catch on my insert customer form, but it just slips through my if statement to the else everytime. This is the source. Also I tried a .Equals with the same results :(
Protected Sub srcAllClients_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles srcAllClients.Inserting
'Establish Variables
Dim emailAddress As String
Dim srcUsers As SqlDataSource = New SqlDataSource()
srcUsers.ConnectionString = ConfigurationManager.ConnectionStrings("ISSD21ConnectionString").ConnectionString
Dim view As DataView
view = DirectCast(srcUsers.Select(DataSourceSelectArguments.Empty), DataView)
srcUsers.SelectCommand = "SELECT EmailAddress FROM ISSDClients"
srcUsers.DataSourceMode = SqlDataSourceMode.DataReader
Dim reader As IDataReader
reader = DirectCast(srcUsers.Select(DataSourceSelectArguments.Empty), IDataReader)
emailAddress = FormView1.FindControl("txtEmail").ToString
While reader.Read()
If reader("EmailAddress") = (emailAddress) Then
lblError.Text = "Your Email is NOT Unique!"
'this is where we cancel the update and return an error
Else
lblError.Text = "Your Email is Unique!"
'nothing needs to happen, maybe just tell them that it went through
End If
End While
reader.Close()
End Sub
emailAddress = FormView1.FindControl("txtEmail").ToString
is just going to return the string "System.Web.UI.WebControls.TextBox". You're not accessing the actual property of the control that would hold the text value, you're just calling ToString() on the control itself.
Try this:
Dim emailBox As TextBox = CType(FormView1.FindControl("txtEmail"), TextBox);
emailAddress = emailBox.Text
In addition to Womp's answer...
In the while loop that is running through the email records, you need to break out of the loop once you find a matching email and alert the user.
if reader("EmailAddress") = (emailAddress) then
'1. Break from the Loop
End if
I would recommend that you pass the emailAddress to the SQL Server as a parameter.
Select Count(EmailAddress) From ISSDClients
Where EmailAddress = #EmailAddress
Execute this statement using ExecuteScalar and cast the result as an integer. If the result is zero then you are ok, otherwise display an error.
Doing it this way avoids using the while loop and should be much quicker if your table has lots of rows.
You also need to get the Text property from the Email Text box.
emailAddress = FormView1.FindControl("txtEmail").Text.ToString
You may want to take a look at the String.Compare method, which will make it easier to compare without respect to things like case sensitivity and culture. It does consider whitespace to be part of your string, so you may wish to trim the string prior to calling it, to help normalize.
For example, the following strings would be considered equal:
var firstString = "some StrinG to Compare ";
var secondString = " somE string to COMPARE";
var equal = (String.Compare(firstString.Trim(), secondString.Trim(), StringComparison.InvariantCultureIgnoreCase) == 0);

Resources