why i get System.IndexOutOfRangeException: EmpPassword - asp.net

myreader = obj.ExecuteReader
If myreader.Read Then
Session.Item("emp_id") = myreader("emp_id")
Session.Item("Email") = myreader("e_mail")
Session.Item("password") = myreader("EmpPassword")
ElseIf TextBox1.Text = "123456" Then
Response.Redirect("home.aspx")
Else
Response.Redirect("personal.aspx")
End If

The error is generated when you try to read a field from the reader that is not present in the SELECT field list of your query. So, if you want to read the EmpPassword value you need to change your query to
Dim query = "SELECT emp_id, E_mail, EmpPassword from personaldetails " & _
"where [E_mail] =#E_mail and EmpPassword =#EmpPassword"
Dim obj = new SqlCommand(query, connection)
.... add the parameters....
myreader = obj.ExecuteReader
.......
However, you already know the password and the email value because you need to set the parameters required by the where clause, so you could avoid to read them from the reader and add the fields to the select list.

Select statement should include all fields that you want to retrieve -
SELECT emp_id, [E_mail], EmpPassword
FROM personaldetails
WHERE [E_mail] = #E_mail
AND EmpPassword = #EmpPassword
- OR -
Since you already know e_mail and EmpPassword, you can select emp_id only, and assign e_mail and EmpPassword from original values -
select [emp_id] from personaldetails
where [E_mail] =#E_mail and EmpPassword =#EmpPassword
Session.Item("emp_id") = myreader("emp_id")
Session.Item("Email") = e_mail
Session.Item("password") = EmpPassword

Related

Dynamic query as a parameter in stored procedure and SQL Injection

I have the following stored procedure (modified for this post):
ALTER PROCEDURE [dbo].[SEL_ARTICLE](
#FILTER VARCHAR(8000) = ''
) AS
BEGIN
DECLARE #SQLQuery varchar(8000);
SET #SQLQuery = 'SELECT DISTINCT ArticleNo, desc, ...
FROM Article INNER JOIN
...
{0}
ORDER BY ArticleNo, ...';
SET #SQLQuery = REPLACE(#SQLQuery, '{0}', #FILTER);
EXEC(#SQLQuery);
END
I call this proc in my prog like this:
Public Function get_Article(ByVal strFilter As String) As DataTable
Dim tblData As New DataTable
Dim par As SqlParameter = New SqlParameter("#FILTER", SqlDbType.VarChar)
par.Value = strFilter
Load_Data("SEL_ARTICLE", tblData, par) 'SqlCommand used
Return tblData
End Function
The value of the parameter strFilter is dynamic (Fields, values) depending on what we search. Here is an example:
" AND ((Article = [input from User]) OR (Description LIKE '%[input from User]%'))"
The user must be able to enter the character ' (word in French) it is why I replace it server-side like this:
strFilter &= String.Format(" AND ((Article = {0}) OR (description LIKE '%{1}%'))", strArticleNo, strArticleName.Replace("'", "''"))
I prevent the user to enter the following characters: <,>,{,},;
Now my question:
Is this code safe against SQL injection attacks ?
Thank you!

Read multiple items from list box to query information from a database

Ok so what I'm trying to do is allow the users of my web form in asp.net to select multiple assets from a list box. When they select these assets and press the select button it fires the following code which should run through the selected indices, query the DB for the description and asset tag's, and populate the Description and Asset tag boxes with those values. Working through this I've been able to get it to read the values from the database and populate the fields but it would only populate the value from the first selected item and it would just insert the same value equal to the number of times equal to the number of items selected in the inbox. I tried my current code to run through the indices a little better but it seems to be failing the If statement and I just can't figure out why. Any help is appreciated, thanks everyone!
Dim i As Integer
For i = 0 To lstAssets.GetSelectedIndices.Count
If lstAssets.Items(i).Selected = True Then
Dim str2 As String = lstAssets.Items(i).Value.ToString
Dim cs As New OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings("CSIWebUpd").ConnectionString)
Dim ds As String = cs.DataSource
Dim cn As OracleConnection = New OracleConnection("user id=webupd;password=webupd;data source=" + ds)
Dim sql As String = "SELECT description, tag FROM assets WHERE id = :id"
Dim cmd As New OracleCommand(sql, cn)
cmd.Parameters.Add(":id", OracleDbType.Varchar2).Value = str2
cmd.CommandType = CommandType.Text
cmd.BindByName = True
cn.Open()
Dim dr As OracleDataReader = cmd.ExecuteReader()
cmd.ExecuteNonQuery()
dr.Read()
desc = dr.GetString(0).ToString
ass = dr.GetString(1).ToString
If txtDescription.Text = Nothing Then
txtDescription.Text = dr.GetString(0).ToString
Else
txtDescription.Text = txtDescription.Text + Chr(13) + Chr(10) + dr.GetString(0).ToString
End If
If txtAsset.Text = Nothing Then
txtAsset.Text = dr.GetString(1).ToString
Else
txtAsset.Text = txtAsset.Text + Chr(13) + Chr(10) + dr.GetString(1).ToString
End If
cmd.Dispose()
cn.Close()
End If
Next i
UpdatePanel1.UpdateMode = UpdatePanelUpdateMode.Conditional
UpdatePanel1.Update()
I would work with the SelectedIndices values in this way
For Each i in lstAssets.GetSelectedIndices
Now i contains the index of the items selected not the offset of the GetSelectedIndices array
The GetSelectedIndices returns an array where every element of the array is the index in the Items collection where you have an item selected.
An example could explain better:
Supposing the the items selected are 1, 5 6 (Count=3), your code set the value of i to 0,1,2 and then uses that value to lookup the ID in the items collection, but the following check on lstAssets.Items(i).Selected found just the item at index 1 as selected. Instead using the for each approach you get the values 1,5,6.

We would like to register a user if space is available or put on waiting list if space is full. Any ideas how to approach this?

I am trying to create a waiting list.
The idea behind this waiting list is that we have a training problem that requires users to sign up for a seat in the class.
There is a maximum capacity seating of 45 people.
If all 45 seats have been occupied, then available_seating which starts at 45 and decreases per course registration, will be 0.
If available_seating is 0, that means that the class is full and no seatings are available.
When a user attempts to sign up for a class where available_seating = 0, we would want to let the user know that this class is full and
s/he will be put on waiting list.
I think I know how to solve this problem.
When available_seating > 0 insert the user into tblTrainings table.
However, if available_seating = 0 then insert user into a table called waitingList.
My problem is how to blend that conditional statement with the counter below.
Below, the SELECT Count(*) query checks to see if user has already registered for a particular class.
If no, register the user for the class. If yes, alert the user that s/he has already registered for the class.
How do I integrate the two in such that we first check to see if the user has already registered for the class.
If no, then we check whether the class is not full yet. If full, insert user into waitingList. If not full, insert user into tblTrainings.
See current code and thanks a lot in advance.
'If user already registered for a class, alert user
s = "SELECT Count(*) FROM tblTrainings WHERE Username = '" & username & "' AND CourseID = " & Request.QueryString("cosId") & " AND LocationID = " & Request.QueryString("locid") & " AND dateId = " & Request.QueryString("iddate") & ""
Dim connSt As String = ConfigurationManager.ConnectionStrings("DBConnectionString").ConnectionString
Dim connc As New SqlConnection(connSt)
Dim cmdc As New SqlCommand(s, connc)
connc.Open()
cmdc.ExecuteNonQuery()
counter = cmdc.ExecuteScalar()
' Now let's see if we found existing record
If counter = 0 Then
'User hasn't signed up for this class yet
s = "INSERT INTO tblTrainings (CourseId, tblLocations.LocationId, dateId,AvailableSeats,username) VALUES (#CosID, #LocID, #dat, #Available_Seating, #Username)"
Dim cmd = New SqlCommand(s, conn)
cmd.Parameters.AddWithValue("#cosID", Request.QueryString("cosId"))
cmd.Parameters.AddWithValue("#locID", Request.QueryString("locid"))
cmd.Parameters.AddWithValue("#dat", Request.QueryString("iddate"))
cmd.Parameters.AddWithValue("#Available_Seating", 45 - 1)
cmd.Parameters.AddWithValue("#UserName", username)
conn.Open()
Maybe I'm missing something, but it doesn't seem that complicated to me.
This answer only uses the SQL pieces that matter to preserve legibility, since I'm mainly referring to queries and not the VB.
First, you do what you were already doing--check to see if they're already signed up/on the waiting list.
SELECT Count(*) FROM (
SELECT * FROM tblTrainings UNION SELECT * FROM waitingList
) AS t
WHERE Username = XXX AND CourseID = XXX AND LocationID = XXX AND dateID = XXX
/* Tells you whether the person is signed up already, whether for the course itself
or the waiting list. */
SELECT Count(*) FROM tblTrainings
WHERE CourseID = XXX AND LocationID = XXX AND dateID = XXX
-- This will give you the number of people in the course.
Then, once you have that, you can decide whether to add them to that table or add them to waiting list.
Update
Maybe this will help.
'Here build your querystring s from the SQL query above, filling in whatever values your need.
s = "SELECT Count(*) FROM (" & _
"SELECT * FROM tblTrainings UNION SELECT * FROM waitingList" & _
") AS t" & _
"WHERE Username = XXX AND CourseID = XXX AND LocationID = XXX AND dateID = XXX"
Dim connSt As String = ConfigurationManager.ConnectionStrings("DBConnectionString").ConnectionString
Dim connc As New SqlConnection(connSt)
Dim cmdc As New SqlCommand(s, connc)
connc.Open()
cmdc.ExecuteNonQuery()
counter = cmdc.ExecuteScalar()
If counter = 0 Then 'this means that the person is in neither the waitlist nor courselist
'Fill in the XXX as necessary
qs = "SELECT Count(*) FROM tblTrainings WHERE CourseID = XXX AND LocationID = XXX AND dateID = XXX"
Set cmdc = New SqlCommand(s, connc)
cmdc.ExecuteNonQuery()
courseSize = cmdc.ExecuteScalar()
If courseSize <= 45 Then
'Insert the guy into the course
Else
'Insert the guy into waitList
End If
End If
Let's say you have a TableA and you want to insert a record only when TableB count is zero. Then you could write this:
insert into TableA (ColA, ColB)
select 'a', 'b' from TableB
where 0 = (select count(*)
from TableB
where ColC = 'c')
It should be easy to fit the above statement to your scenario.

How can I update a database table programmatically?

I have a button which when pressed, sets the user's rights in the db. (If Administrator UserTypeID is set to '2' and if Customer it is set to '1'). However when I run the below code, everything remains the same. I think it's from the SQL statement but I;m not sure. Can anyone help please?
Protected Sub btnSetUser_Click(sender As Object, e As System.EventArgs) _
Handles btnSetUser.Click
Dim conn As New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\...\WebSite3\db.mdb;")
Dim cmd As OleDbCommand = _
New OleDbCommand("UPDATE [User] SET [UserTypeID] WHERE Username=?", conn)
conn.Open()
cmd.Parameters.AddWithValue("#Username", txtUser.Text)
If ddUserType.SelectedItem.Text = "Administrator" Then
cmd.Parameters.AddWithValue("#UserTypeID", "2")
cmd.ExecuteNonQuery()
lblSetUser.Text = txtUser.Text + "was set to Administrator."
ElseIf ddUserType.SelectedItem.Text = "Customer" Then
cmd.Parameters.AddWithValue("#UserTypeID", "1")
cmd.ExecuteNonQuery()
lblSetUser.Text = txtUser.Text + "was set to Customer."
End If
conn.Close()
End Sub
End Class
If you add a parameter #Username your command should have such a parameter
SELECT [UserTypeID] FROM [User] WHERE Username = #Username
Also, you add an additional parameter later, which does not occur at all in your query! You call cmd.ExecuteNonQuery(), which works only for INSERT, UPDATE and DELETE queries.
Your query should probably look like this
UPDATE [User]
SET UserTypeID = #UserTypeID
WHERE Username = #Username
Dim cmd As OleDbCommand = New OleDbCommand( _
"UPDATE [User] SET UserTypeID = #UserTypeID WHERE Username = #Username", conn)
Dim userType As String = ddUserType.SelectedItem.Text
Dim userTypeId As Integer = If(userType = "Administrator", 2, 1)
cmd.Parameters.AddWithValue("#UserTypeID", userTypeId)
cmd.Parameters.AddWithValue("#Username", txtUser.Text)
conn.Open()
cmd.ExecuteNonQuery()
lblSetUser.Text = txtUser.Text + "was set to " & userType
UPDATE (some clarifications)
In "UDATE [User] SET UserTypeID = #UserTypeID WHERE Username = #Username"
[User] is the name of the table
UserTypeID is the name of the user type id column
#UserTypeID is the name of the user type id parameter (the new value)
Username is the name of the user name column
#Username is the name of the user name parameter
You might have to change these names in order to match your actual situation.
You are only performing a Select Query - which will not modify any data at all.
You will want to use an Update Query, supplying parameters for both the username and the user rights number.
You're doing a SELECT instead of an UPDATE...
New OleDbCommand("SELECT [UserTypeID] FROM [User] WHERE Username=?", conn)
should be
New OleDbCommand("UPDATE [User] SET [UserTypeID] = #UserTypeID WHERE Username = #Username", conn)

Changing the selected value of a drop down based on the selected value of another drop down in VB.Net

I have a dropdown box which is used to select a user from a database. I am then populating a number of textboxes with the user information from the database. I want to populate a dropdown box, which holds the user's role, dependent on which user is selected from the first drop down box.
Here is my code:
Dim currentUser As String = editUserDropDown.SelectedValue
Dim getUserDetails = "Select aspnet_Users.UserName, aspnet_Roles.RoleName, [User Details].EmployeeName, [User Details].EmployeeAddress, [User Details].PersonalEmailAddress FROM aspnet_Users INNER JOIN [User Details] ON aspnet_Users.UserId = [User Details].UserId CROSS JOIN aspnet_Roles WHERE (aspnet_Users.UserName = '" & currentUser & "')"
Dim getUserDetailsCmd As New SqlClient.SqlDataAdapter(getUserDetails, DBConn)
Dim getUserDetailsDS As New DataSet
getUserDetailsCmd.Fill(getUserDetailsDS)
Dim username = getUserDetailsDS.Tables(0).Rows(0).Item(0)
Dim roleName = getUserDetailsDS.Tables(0).Rows(0).Item(1)
Dim name = getUserDetailsDS.Tables(0).Rows(0).Item(2)
Dim address = getUserDetailsDS.Tables(0).Rows(0).Item(3)
Dim email = getUserDetailsDS.Tables(0).Rows(0).Item(4)
userNameTxt.Text = username
roleSelect.SelectedValue = roleName
nameTxt.Text = name
addressTxt.Text = address.Trim()
emailTxt.Text = email
any help is greatly appreciated
You have to do this by doing a Post-back on the fist select drop down and then getting the content for the second one depending of the selection made on the first...
Hoped that helped!

Resources