vb.net login control not re-authenticating - vb.net

I am newbie when it comes to working with the vb.net login control so bear with me...
Tp start I am using ASP.net 4.0 and vb.net.
Okay so I have a simple login control that verifies the user against a sql database. (I am hosting with hostgator so I can't use the normal windows auth). Now the biggest probelm I am having is that if the session times out and you get redirected to the login page it doesn't matter what you type in the user name/password on the login in form it just lets you right in even if the user name and password are wrong or the user doesn't exist?
How do I make sure that the login control truly authenticates the user?
Any help is greatly appreciated.
Thanks!
Public strLoginErrorMsg As String
Public type As String
Public rowcount As String
Protected Sub login_sbts_Authenticate(sender As Object, e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles login_sbts.Authenticate
Dim bauthenticated As Boolean = False
bauthenticated = isValidUser(login_sbts.UserName, login_sbts.Password)
If bauthenticated Then
e.Authenticated = True
Else
e.Authenticated = False
End If
lblInfo.Text = type
FormsAuthentication.RedirectFromLoginPage(Me.login_sbts.UserName, True)
If type = "ADMIN" Then
Response.Redirect("dailynote.aspx")
Else
Response.Redirect("other.aspx")
End If
End Sub
Private Function isValidUser(ByVal username As String, ByVal pwd As String) As [Boolean]
Dim con As New SqlConnection("Data Source=localhost;Initial Catalog=sbts-scheduling;User ID=userid;Password=password;")
Dim cmd As New SqlCommand("select * from tblusers where UserName='" & username & "' and Password='" & pwd & "'")
cmd.Connection = con
Dim dt As New DataTable()
Dim da As New SqlDataAdapter(cmd)
con.Open()
da.Fill(dt)
con.Close()
If dt.Rows.Count = 0 Then
strLoginErrorMsg = "Invalid User Name/Password"
dt.Dispose()
Return False
Else
type = dt.Rows(0).Item("UserType").Trim()
Session("usertype") = type
End If
Return True
End Function
Protected Sub login_sbts_LoginError(sender As Object, e As System.EventArgs) Handles login_sbts.LoginError
login_sbts.FailureText = strLoginErrorMsg
End Sub

Actually.. the problem may lye in your call to FormsAuthentication.RedirectFromLoginPage.. I took the liberty of cleaning up your code a bit though. I also added FormsAuthentication.SetAuthCookie in your authentication method.. the name and duration of that cookie will be configured in your web.config file.. or your 'configuration settings'.
Unless you're willing to inherit, clear, and replace the ASP.NET default FormAuthenticationModule.. you're going to have to rely on, in part, the web.config configuration settings.
Public strLoginErrorMsg As String
Public type As String
Public rowcount As String
Protected Sub login_sbts_Authenticate(sender As Object, e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles login_sbts.Authenticate
If isValidUser(login_sbts.UserName, login_sbts.Password) Then
e.Authenticated = True
FormsAuthentication.SetAuthCookie(login_sbts.UserName, false, "/")
lblInfo.Text = type
If type = "ADMIN" Then
Response.Redirect("dailynote.aspx")
Else
FormsAuthentication.RedirectFromLoginPage(Me.login_sbts.UserName, True)
'Response.Redirect("other.aspx")
End If
Else
e.Authenticated = false
End If
End Sub
Private Function isValidUser(ByVal username As String, ByVal pwd As String) As Boolean
isValidUser = False
Dim conn As New SqlConnection("Data Source=localhost;Initial Catalog=sbts-scheduling;User ID=userid;Password=password;")
Dim cmd As New SqlCommand("select * from tblusers where UserName='" & username & "' and Password='" & pwd & "'", conn)
Using conn
conn.open
Using reader As system.data.sqlclient.SqlDataReader = comm.ExecuteReader
If reader.Count > 0 Then
'Not Checking for multible records here.
While reader.read
If Not( IsDBNull(reader("UserType")) Then
Session("usertype") = reader("UserType").Trim()
IsValidUser = True
End If
End While
End If
End Using
If Not( conn.State = State.Close) Then
conn.Close
End If
End Using
End Function
Protected Sub login_sbts_LoginError(sender As Object, e As System.EventArgs) Handles login_sbts.LoginError
login_sbts.FailureText = strLoginErrorMsg
End Sub
I recommend you look into inheriting MembershipProvider. It makes working with the asp server tags a bit easier, as you simply specify your provider in the property of the tag. (after you reference and configure it properly in your web.config, app.config.. or through IIS (will require being placed in Global Cache Assembly and all the other loops to becoming a Trusted Provider.)

Related

How to query database for log in form in Visual Studio+Basic?

Trying to learn Visual Studio, I was able to create a static log in form e.g. check if the text box and password match the hard coded data, but I just cannot get the Access query to work. I've ran through 6 different efforts (cleared them all until this point)
Imports System.Data.OleDb
Public Class Login
Dim con As New OleDbConnection
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\someone\source\repos\Test\Test\vs.mdb"
con.Open()
Dim logincmd As New OleDbCommand("Select * From tblLogin WHERE userName = " & tbUser.Text, con)
Dim loginrd As OleDbDataReader = logincmd.ExecuteReader
If (loginrd.Read() = True) Then
MenuPage.Show()
Me.Close()
Else
MsgBox("Sorry that's not right")
End If
End Sub
Error: System.Data.OleDb.OleDbException: 'No value given for one or more required parameters.'
On line: Dim loginrd As OleDbDataReader = logincmd.ExecuteReader
Please tell me where I'm going wrong?
EDIT: I've found some code that works, so I'm going to cross reference the two and try work out why the above code didn't work, might help me get a better understanding of things!
Database objects like Connections and Commands need to be disposed. Using...End Using blocks handle this for us. They both declare and dispose the objects. In this code both the connection and command are handled by a single Using block. Note the comma on the first line of the Using.
You can pass the connection string directly to the constructor of the connection. You can also pass the CommandText and Connection directly to the constructor of the command. A constructor will be indicated by the New keyword.
Always use parameters to help defeat sql injection. Parameters will not be treated as executable code by the database.
Don't open the connection until directly before the Execute statement and close and dispose as soon as possible with End Using.
Since we are only seeking a single piece of data (the count) we can use ExecuteScalar which returns the first column of the first row of the result set.
Private ConnStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\someone\source\repos\Test\Test\vs.mdb"
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
'Validate input
If txtUserName.Text = "" OrElse txtPassword.Text = "" Then
MessageBox.Show("Please fill in both Name and Password.")
Exit Sub
End If
If ValidateLogin(txtUserName.Text, txtPassword.Text) Then
MenuPage.Show()
Me.Close()
Else
MessageBox.Show("Invalid Login")
End If
End Sub
Private Function ValidateLogin(uName As String, pWord As String) As Boolean
Dim IsValid As Boolean
Dim ReturnValue As Integer
Using cn As New OleDbConnection(ConnStr),
cmd As New OleDbCommand("Select Count(*) From tblLogin Where userName = #UserName AND passWord = #Password;", con)
cmd.Parameters.Add("#UserName", OleDbType.VarChar).Value = uName
cmd.Parameters.Add("#Password", OleDbType.VarChar).Value = pWord
cn.Open()
ReturnValue = CInt(cmd.ExecuteScalar)
End Using
If ReturnValue = 1 Then
IsValid = True
End If
Return IsValid
End Function
Of course, you should never store passwords as plain text. Investigate encryption and salting.
I'd suggest
Separating login code from form code
Never use string concatenation for SQL parameters, use command parameters.
Encrypting the database
If exception.Message.ToLower.Contains("not a valid password") Then in this case is for an encrypted database, ignore if not encrypting the database.
Recommend a class for login (table columns shown are different from yours but the logic will work no matter)
Login class
Permits three attempts at a login.
Imports System.Data.OleDb
Public Class ApplicationLogin
Private ReadOnly ConnectionString As String
Public Property UserName As String
Public Property UserPassword As String
Public Property Retries As Integer
Private Userid As Integer
Public ReadOnly Property UserIdentifier As Integer
Get
Return Userid
End Get
End Property
Public Sub New(pConnectionString As String)
ConnectionString = pConnectionString
End Sub
Public Function Login() As Boolean
If Not String.IsNullOrWhiteSpace(Me.UserName) AndAlso Not String.IsNullOrWhiteSpace(Me.UserPassword) Then
Using cn As New OleDbConnection With {.ConnectionString = ConnectionString}
Using cmd As New OleDbCommand With
{
.Connection = cn,
.CommandText =
"SELECT Identifer, UserName, UserPassword FROM Users " &
"WHERE UserName = #UserName AND UserPassword = #UserPassword"
}
cmd.Parameters.Add("#UserName", OleDbType.LongVarChar).Value = UserName
cmd.Parameters.Add("#UserPassword", OleDbType.LongVarChar).Value = UserPassword
Try
cn.Open()
Catch exception As Exception
If exception.Message.ToLower.Contains("not a valid password") Then
Return False
Else
Throw
End If
End Try
Dim reader = cmd.ExecuteScalar
If reader IsNot Nothing Then
Userid = CInt(reader)
Retries = 0
Return True
Else
Retries += 1
Return False
End If
End Using
End Using
Else
Return False
End If
End Function
End Class
Form code
Public Class Form1
Private Retries As Integer = 0
Private Sub LoginButton_Click(sender As Object, e As EventArgs) Handles LoginButton.Click
Dim appLogin As New ApplicationLogin("Your connection string") With
{.UserName = txtUserName.Text, .UserPassword = txtPassword.Text}
If appLogin.Login Then
' login successful
Else
Retries += 1
' too many retries
End If
End Sub
End Class
Full source (not done with .mdb but .accdb)
Front end project
Class project for login logic
Database encryption docs

How do i get the data to my database using vb.net (class, module and form)

I hope the title is enough to understand my problem, I already installed whats need to run the ADO.NET, I already have a connection string in my module and data query in my class,
Imports System.Data
Imports System.Data.OleDb
Module GlobalVariables
Public sGlobalConnectionString As String
Friend conString As String
Public dr As OleDbDataReader
Sub Main()
Dim sGlobalConnectionString As New OleDb.OleDbConnection
Dim sDataserver As String
Dim sDatabaseName As String
Dim sDatabaseConnection As String
sDataserver = "localhost"
sDatabaseName = "employee"
sDatabaseConnection = "Driver={MariaDB ODBC 3.1 Driver}; SERVER=" & sDataserver & "; UID=root;PWD=******; Database=" & sDatabaseName & "; PORT=3307; OPTION=3"
sGlobalConnectionString = New OleDb.OleDbConnection(conString)
End Sub
End Module
this is my class
Imports System.Data.OleDb
Public Class clsDataQuery
Public Shared Sub Class_initialize()
Dim con = New OleDb.OleDbConnection
con.ConnectionString = sGlobalConnectionString
con.Open()
End Sub
Public Shared Sub Class_Terminate()
Dim con = New OleDb.OleDbConnection
If Not con Is Nothing Then
con.Close()
con = Nothing
End If
End Sub
Public Function GetRecordDataSet(ByVal sStoreProcName As String, ByVal sParameterList As String)
Dim cmd As New OleDbCommand()
Dim arrParameter, arrParamName
Dim sParamName As String
Dim sDataValue
Dim lCtr As Long
On Error GoTo errhandler
cmd.Connection = New OleDb.OleDbConnection
cmd.CommandTimeout = 1800
cmd.CommandText = CommandType.Text
If Not Trim(sParameterList) = "" Then
arrParameter = Split(sParameterList, "|", , vbTextCompare)
If UBound(arrParameter) >= 0 And IsArray(arrParameter) Then
For lCtr = 0 To UBound(arrParameter)
arrParamName = Split(arrParameter(lCtr), "$", , vbTextCompare)
sParamName = arrParamName(0)
sDataValue = arrParamName(1)
cmd.Parameters.Item(sParamName) = sDataValue
Next lCtr
End If
End If
GetRecordDataSet = cmd.ExecuteReader
cmd = Nothing
Exit Function
errhandler:
MessageBox.Show("Records Not Found!!!")
End Function
End Class
if this button is click, the value of Textbox1.text will search in the database if it is exist, if exist it will continue into another form if not error message will appear, how do i do that?
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim username = txtbox_lastname.Text
If username <> "" Then
Try
clsDataQuery.Class_initialize()
Catch ex As Exception
MessageBox.Show("No Record Found")
End Try
Else
MessageBox.Show("No Record Found!!!")
End If
End Sub
If this is MariaDb then you want to use the provider for MySql. Not ODBC and not OleDb. No wonder you are having problems. There is not much information available for this database compared to the usual Access database used for beginners.
Do not declare database objects anywhere but the method they are used in. You can declare a Private variable for the connection string at the class level.
Although one of these is a Module level variable and one is a local variable, it is very confusing and bad practice. Why would you call a connection object a String?
Public sGlobalConnectionString As String
Dim sGlobalConnectionString As New OleDb.OleDbConnection
BTW, it is fine to declare and initialize your variables in a single line.
Dim sDataserver = "localhost"
You create a new connection on the first line of Sub Main, then you throw it away and create another new connection on the last line. Since sDataServer and sDatabaseName are hard coded why not just put the literal values directly into the connection string.
After all that you pass conStr to the constructor of the connection instead of sDatabaseConnection. Why were you building sDatabaseConnection (another misnomer, it is not a connection, its a string) and then never use it. Has conStr been set elsewhere?
At any rate, throw out the whole module.
Moving on to your DataQuery class. First, the name should begin with an upper case letter.
Get rid of Class_initialize. We don't want to create or open any connection except in the method where it is used. You never call Class_Terminate so dump that too.
The GetRecordDataSet method...
Functions in vb.net require a datatype. The old VB6 syntax of assigning the return value to the name of the function will work but it is not the .net way. In vb.net we use the Return keyword.
You have not initialized or given a datatype to arrParameter, arrParamName or sDataValue which violates Option Strict. (You do have Option Strict On, don't you?)
On Error GoTo errhandler is a sad leftover from VB6. .net languages have structured error handling with Try...Catch...Finally...End Try.
cmd.Connection = New OleDb.OleDbConnection sets the connection property however this new connection has no connection string.
cmd.CommandText = CommandType.Text Now this is just silly. What I think you want is cmd.CommandType =CommandType.StoredProcedure
Using...End Using blocks take care of declaring, closing and disposing database objects even if there is an error. You don't want to return a DataReader because a reader requires an open connection. cmd.ExecuteReader returns a DataReader. I used the reader to load a DataTable and returned the DataTable.
It seems you are trying to develop a factory pattern but it is way too advanced for your. Just pass value and call a method specific to what your are searching for. You want your DataQuery code to be independent from your user interface. The Button code doesn't care where the data is coming from. It could be a database, a text file, or a web service. Likewise the DataQuery code doesn't know where the values are coming from. It could be a WinForms app, a web application or a phone app.
Public Class DataQuery
Private Shared ConStr As String = "server=localhost;userid=root;database=employee"
Public Shared Function SearchByLastName(ByVal LName As String) As DataTable
Dim dt As New DataTable
Using cn As New MySqlConnection(ConStr),
cmd As New MySqlCommand("Select * From PutTableNameHere Where LastName = #LName", cn)
cmd.Parameters.Add("#LName", MySqlDbType.VarChar).Value = LName
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
End Class
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt As DataTable = Nothing
If txtbox_lastname.Text <> "" Then
Try
dt = DataQuery.SearchByLastName(txtbox_lastname.Text)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
DataGridView1.DataSource = dt
End Sub
Before answering, I really think that the GetRecordDataSet() at the very least a darn good tidy up, better yet removed from history
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim username = txtbox_lastname.Text
If username <> "" Then
Try
clsDataQuery.Class_initialize()
Dim reader = GetRecordDataSet("storedProcName", txtbox_lastName.Text)
Do While reader.Read()
'Process record etc
Loop
Catch ex As Exception
MessageBox.Show("No Record Found")
End Try
Else
MessageBox.Show("No Record Found!!!")
End If
End Sub
Might be a bit rough, but should get you heading in the right direction

How to get the primary key value while executing the query?

This is the Login Button code and EditUser() function:
Private Sub BtnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
If (isformvalid()) Then
qr = "Select * from userlogin where UserName='" & txtUser.Text & "' and Password='" & txtPassword.Text & "' and UserType ='" & ComboBox1.Text & "' "
ds = searchdata(qr)
If (ds.Tables(0).Rows.Count > 0) Then
LoginUser = txtUser.Text
LoginPass = txtPassword.Text
UserType = ComboBox1.Text
EditUser()
Dashbord.Show()
Me.Close()
Else
MsgBox("UserName or Password is Incorrect. Please Cheak And Try Again")
txtUser.ResetText()
txtPassword.ResetText()
End If
End If
End Sub
Private Function EditUser()
If (isformvalid()) Then
q = "Insert into UserLoginAudit (UserName, Password, UserType, ActivityLogin) Values('" & txtUser.Text & "','" & txtPassword.Text & "','" & ComboBox1.Text & "','" & DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") & "')"
ProID = lastProID(q)
End If
End Function
This is the module code:
Module DBSQLServer
Public con As New SqlConnection("Data Source=JOYALXDESKTOP\SQLEXPRESS;Initial Catalog=SaleInventory;Integrated Security=True")
Public cmd As New SqlCommand
Public da As New SqlDataAdapter
Public ds As New DataSet
Public dt As DataTable
Public qr As String
Public i As Integer
Public newProID As Integer
Public Function searchdata(ByVal qr As String) As DataSet
da = New SqlDataAdapter(qr, con)
ds = New DataSet
da.Fill(ds)
Return ds
End Function
Public Function insertdata(ByVal qr As String) As Integer
cmd = New SqlCommand(qr, con)
con.Open()
i = cmd.ExecuteNonQuery()
con.Close()
Return i
End Function
Public Function lastProID(ByVal qr As String) As Integer
cmd = New SqlCommand(qr, con)
con.Open()
newProID = cmd.ExecuteScalar
con.Close()
Return newProID
End Function
End Module
And this is my Logout code and EditUser() function:
Private Sub Label1_Click_1(sender As Object, e As EventArgs) Handles Label1.Click
Application.Exit()
EditUser()
End Sub
Private Function EditUser()
q0 = "UPDATE UserLoginAudit SET ActivityOffline = '" & DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") & "' WHERE AuditID = '" & My.Forms.login.ProID & "';"
Dim logincorrect As Boolean = Convert.ToBoolean(insertdata(q0))
If (logincorrect) Then
MsgBox("LogOut Successful ...", MsgBoxStyle.Information)
Else
MsgBox("Something Wrong. LogOut Failed. Please Check and Try Again...", MsgBoxStyle.Critical)
End If
End Function
When I run the program, after clicking the login button the data (UserName, Password, UserType, ActivityLogin) is inserted perfectly.
But when I click the Logout button in the database ActivityOffline column value remains null.
Then I create a Form Load event to check the value of ProID in the main form where I created the logout button:
Private Sub Dashbord_Load(sender As Object, e As EventArgs) Handles MyBase.Load
hi.Text = My.Forms.login.ProID
End Sub
It always shows 0
There's a LOT in here, so take some time to read through and understand all the changes... because some of these things that might seem trivial are actually very important:
Module DBSQLServer
'Don't try to re-use the connection object. It interferes with connection pooling and makes things worse, rather than better
'Instead, just re-use the connection string
Private ConnectionString As String = "Connection String here"
'Make this private. Then have a public method for each actual query you use
'It will force you to create a cleaner separation between DB and UI
'If this starts to make for a really huge module, move this to a separate class library, where the public methods are divided up into separate modules for logical groupings and the private methods are in a common Friend module using the InternalsVisibleTo attribute
Private Function searchdata(sql As String, ParamArray data() As SqlParameter) As DataSet
Dim result As New DataSet()
Using cn As New SqlConnection(ConnectionString), _
cmd As New SqlCommand(sql, cn), _
da As New SqlDataAdapter(cmd)
If data IsNot Nothing Then
For Each parameter As SqlParameter In data
cmd.Parameters.Add(parameter)
Next
End If
da.Fill(result)
End Using
Return result
End Function
' This may need some work yet
Private Function GetValue(Of T)(ByVal qr As String, ParamArray data() As SqlParameter) As T
Using cn As New SqlConnection(ConnectionString), _
cmd = New SqlCommand(qr, con)
If data IsNot Nothing Then
For Each parameter As SqlParameter In data
cmd.Parameters.Add(parameter)
Next
End If
con.Open()
' To do: better handling for NULL
Return CType(cmd.ExecuteScalar(), T)
End Using
End Function
'Now the Public methods
Public Function ValidateCredentials(Username As String, HashedPassword As String, UserType As String) As Integer
Dim qr As String = "Select * from userlogin where UserName= #Username and Password= #Password and UserType = #UserType"
'Match the parameter declarations to the database column types and lengths
Dim u As New SqlParameter("#Username", SqlDbType.NVarChar, 20)
u.Value = UserName
'Thanks to hashing, this will be a fixed length
Dim p As New SqlParameter("#Password", SqlDbType.NChar, 60)
p.Value = HashedPassword
Dim t As New SqlParameter("#UserType", SqlDbType.VarChar, 10)
t.Value = UserType
Dim ds As DataSet = searchdata(qr, u, p, t)
If ds.Tables(0).Rows.Count > 0 Then
' Moving this call here, as part of ValidateCredentials, prevents
' any possibility of logging in without also creating an audit
Return CreateUserLoginAuditRecord(Username, Password, UserType)
Else
Return -1
End If
End Function
' Logging Passwords is also a **HUGE** no-no. Please remove that field from your audit table
Public Function CreateUserLoginAuditRecord(Username As String, Password As String, Usertype As String)
'Even better to combine this with the Validate query, as one long sql string handling multiple statements.
Dim qr As String = "Insert into UserLoginAudit (UserName, Password, UserType, ActivityLogin) Values(#UserName, #Password, #UserType, current_timestamp);Select scope_identity;"
Dim u As New SqlParameter("#Username", SqlDbType.NVarChar, 20)
u.Value = UserName
Dim p As New SqlParameter("#Password", SqlDbType.NChar, 60)
p.Value = Password
Dim t As New SqlParameter("#UserType", SqlDbType.VarChar, 10)
t.Value = UserType
Return GetValue(Of Integer)(qr, u, p, t)
End Function
Public Function CloseUserLoginAuditRecord(AuditID As Integer) As Boolean
Dim qr As String = "UPDATE UserLoginAudit SET ActivityOffline = current_timestamp WHERE AuditID = #AuditID"
Dim a As New SqlParameter("#AuditID", SqlDbType.Integer)
a.Value = AuditID
Return GetValue(Of Boolean)(qr, a)
End Function
End Module
Public Function HashPassword(plainText As String) As String
'Leaving this for you. Read up on BCrypt.
'THIS IS IMPORTANT!!!!1!!
Throw New NotImplementedException()
End Function
Private Sub BtnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
If isformvalid() Then
Dim AuditID As Integer = DBSQLServer.ValidateCredentials(txtUser.Text, HashPassword(txtPassword.Text), ComboBox1.Text)
If (AuditID <> -1) Then
'Create ProID as a public property of the Dashboard class
Dashboard.ProID = AuditID
Dashboard.Show()
Me.Close()
Else
MsgBox("UserName or Password is Incorrect. Please Check And Try Again")
txtUser.ResetText()
txtPassword.ResetText()
End If
End If
End Sub
Private Sub Label1_Click_1(sender As Object, e As EventArgs) Handles Label1.Click
' This should really be handled by the form-closing event or similar.
' Event that won't be enough. You can't stop task manager, power failures, OS/application crashes, etc.
' No matter what, you **WILL** end up with a **LOT** of unresolved audits
' Really, it's best just to throw up your hands about this.
' Close what you can, but don't worry about the unclosed audit records, because you really can't stop that...
' ... in which case, you might just remove the MsbBox calls.
If DBSQLServer.CloseUserAuditLoginRecord(ProID) Then
MsgBox("LogOut Successful ...", MsgBoxStyle.Information)
Else
MsgBox("Something went wrong. LogOut Failed. Please Check and Try Again...", MsgBoxStyle.Critical)
End If
Application.Exit()
End Sub
At the end of your Insert statement add a semi colon to indicate the end of the command. Then add
SELECT SCOPE_IDENTITY();
You can then use .ExecuteScalar and expect the new Primary Key to be returned.
However
OUTPUT
it is Microsoft's preferred way to get the value and from the things I've read they have no intention of fixing any problems with ##identity and scope_Identity in the future as they consider OUTPUT to be the replacement.
CREATE PROCEDURE [Sales].[uspNewCustomer]
#CustomerName NVARCHAR (40),
#CustomerID INT OUTPUT
AS
BEGIN
INSERT INTO [Sales].[Customer] (CustomerName) VALUES (#CustomerName);
SET #CustomerID = SCOPE_IDENTITY();
RETURN ##ERROR
END

Unable to redirect user login based on Roles

I'm having some difficulty getting my login to redirect users based on their roles. When I login either a user/admin, they get redirected to the Default.aspx instead of the specified pages. I've been looking at this code too much and can't see anything wrong with it. Any ideas on why I'm having this problem would be extremely appreciated.
This is my Login.aspx
If you have don't have an account, Create one here!<br />
<br />
<asp:Login ID="Login1" runat="server" DisplayRememberMe="true">
</asp:Login>
This is my Login.aspx.vb
Imports System.Data.SqlClient
Imports System.Data
Imports System.Configuration
Imports System.Web.Security
Partial Class ContentPages_Login
Inherits System.Web.UI.Page
Protected Sub page_load(sender As Object, e As EventArgs) Handles Me.Load
If Not Me.IsPostBack Then
If Me.Page.User.Identity.IsAuthenticated Then
FormsAuthentication.SignOut()
Response.Redirect("~/ContentPages/Login.aspx")
Else
Session.Abandon()
Session.Clear()
End If
End If
End Sub
Protected Sub Login1_Authenticate(sender As Object, e As AuthenticateEventArgs) Handles Login1.Authenticate
FormsAuthentication.Initialize()
Dim USER_ID As Integer = 0
Dim roles As String = String.Empty
Dim con As New SqlConnection("Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True")
Using cmd As New SqlCommand("Validate_User")
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#USER_NAME", Login1.UserName)
cmd.Parameters.AddWithValue("#PASSWORD", Login1.Password)
cmd.Connection = con
con.Open()
Dim reader As SqlDataReader = cmd.ExecuteReader()
reader.Read()
USER_ID = Convert.ToInt32(reader("USER_ID"))
roles = reader("Roles").ToString()
con.Close()
End Using
Select Case USER_ID
Case -1
Login1.FailureText = "Username and/or password is incorrect."
Case -2
Login1.FailureText = "Account has not been activated."
Exit Select
Case Else
Dim ticket As New FormsAuthenticationTicket(1, Login1.UserName, DateTime.Now, DateTime.Now.AddMinutes(2880), Login1.RememberMeSet, roles, FormsAuthentication.FormsCookiePath)
Dim hash As String = FormsAuthentication.Encrypt(ticket)
Dim cookie As New HttpCookie(FormsAuthentication.FormsCookieName, hash)
If ticket.IsPersistent Then
cookie.Expires = ticket.Expiration
End If
Response.Cookies.Add(cookie)
Response.Redirect(FormsAuthentication.GetRedirectUrl(Login1.UserName, Login1.RememberMeSet))
If Request.IsAuthenticated AndAlso User.IsInRole("Admin") = True Then
Response.Redirect("~/AdminPages/CustomerList.aspx")
ElseIf Request.IsAuthenticated AndAlso User.IsInRole("User") = True Then
Response.Redirect("~/ClientPages/CustomerProfile.aspx")
End If
Exit Select
End Select
End Sub
End Class
I didn't have the correct location path ="~/foldername" in the webconfig. Now works as intended

OleDbDataReader says that there is no data in the table it is reading from (VB.NET)

My OleDb access database connection correctly counts the number of rows (entries) in a table in the database, but when it comes to reading every instance of one of the fields using a for loop, I get the error that when getting the username (teacher_id/student_id) of the first entry in the table using databaseReader, there is no data in the databaseReader(1) instance.
The error:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Data.dll
Additional information: No data exists for the row/column.
(And btw I am aware that there is no password verification yet)
Imports System.Data
Imports System.Data.OleDb
Public Class LoginForm
Const databaseLocation As String = "C:\Users\Patrick\Documents"
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OKButton.Click
Dim enteredUsername As String = UsernameTextBox.Text
Dim enteredPassword As String = PasswordTextBox.Text
Login(enteredUsername, enteredPassword)
End Sub
Private Sub Cancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelButton.Click
Me.Close()
End Sub
Sub Login(ByRef username As String, ByRef password As String)
Dim isUsernameVerified As Boolean
'This is the admin's username and password, and should not be shown to any other users
If username = "adminentry" And password = "iamanadmin" Then
MenuForm.Show()
Me.Close()
End If
isUsernameVerified = VerifyUsernameAndPassword(username, password)
If isUsernameVerified = True Then
MenuForm.Show()
Me.Close()
Else
LoginComboBox.Text = "Username or password not found"
End If
End Sub
Function VerifyUsernameAndPassword(ByRef usernameForVerification As String, ByRef passwordForVerification As String)
'This string tells the connection where the database is, and which provider to use
Const connectionString As String = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & databaseLocation & "\ProjectDatabase.accdb")
Dim sqlQuery As String
Dim verified As Boolean
'database connection required in order to verify username and password inputs
Using connectionToDatabase As New OleDbConnection(connectionString)
Dim numberOfEntries As Integer
'Open the database connection
connectionToDatabase.Open()
If LoginComboBox.SelectedItem = "Staff login" Then
'sql code for counting number of staff ID's
sqlQuery = "SELECT COUNT(*) AS sqlQuery FROM Teacher_Table"
Else
'sql code for counting number of student ID's
sqlQuery = "SELECT COUNT(*) AS sqlQuery FROM Student_Table"
End If
Dim getNumberOfEntriesCommand As New OleDbCommand(sqlQuery, connectionToDatabase)
'executes counting sql code
numberOfEntries = getNumberOfEntriesCommand.ExecuteScalar
If LoginComboBox.SelectedItem = "Staff login" Then
'sql code for getting staff ID's
sqlQuery = "SELECT teacher_id FROM Teacher_Table"
Else
'sql code for getting student ID's
sqlQuery = "SELECT student_id FROM Student_Table"
End If
Dim loginVerificationCommand As New OleDbCommand(sqlQuery, connectionToDatabase)
'executes verification sql code
Dim databaseReader As OleDbDataReader = loginVerificationCommand.ExecuteReader()
For i = 1 To numberOfEntries
If databaseReader(i) = usernameForVerification Then
verified = True
End If
Next
End Using
If verified = True Then
Return True
Else
Return False
End If
End Function
End Class
This is the wrong model for a data reader. A data reader exposes a current row, and lets you move around the rows. databaseReader(i) would refer to field i in the current row, not row i as your code thinks.
The standard way to use a data reader is
Do While databaseReader.Read
'Do something with the current row
If databaseReader(0) = usernameForVerification Then
verified = True
Exit Loop
End If
Loop
databaseReader.Close
(I've not used VB.Net, so apologies if I've got some syntax wrong)
You'd be much better building queries that include the value to search for. For example:
Select teacher_id From Teacher_Table Where teacher_id = ?
You'd need to learn about parameter binding to utilize this.