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

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

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 to insert and update all the data from datagridview to sql datatable

I want to type all the data in a datagridview and insert into SQL datatable or if the data exist it should update the data in SQL datatable using the datagridview.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each row As DataGridViewRow In DataGridView1.Rows
If row.IsNewRow = False Then
sqlSTR = "SELECT ID, Name, Abbrev FROM TBL_Stream WHERE (Name = '" & row.Cells(0).Value & "')"
ExecuteSQLQuery(sqlSTR)
If sqlDT.Rows.Count > 0 Then
sqlSTR = "UPDATE TBL_Stream SET Name ='" & row.Cells(0).Value & "', Abbrev ='" & row.Cells(1).Value & "' WHERE (Name ='" & row.Cells(0).Value & "')"
ExecuteSQLQuery(sqlSTR)
GetGrid()
MsgBox("Record Updated", MsgBoxStyle.Information, "Update")
Else
sqlSTR = "INSERT INTO TBL_Stream (Name, Abbrev) VALUES ('" & row.Cells(0).Value & "','" & row.Cells(1).Value & "')"
ExecuteSQLQuery(sqlSTR)
GetGrid()
MsgBox("Record Saved", MsgBoxStyle.Information, "Record")
End If
End If
Next
End Sub
I didn't read the question carefully enough to begin with but you can still perform upserts with a data adapter and DataTable. You just start with an empty DataTable, add all the desired rows and then call Update on a data adapter with appropriate upsert SQL in the InsertCommand, e.g.
Private adapter As SqlDataAdapter
Private table As DataTable
Private Sub ConfigureDataAccess()
Dim connection As New SqlConnection("Server=(local);Database=Test;Trusted_Connection=True;")
adapter = New SqlDataAdapter("SELECT * FROM Table_1", connection)
Dim upsertSql = "
IF EXISTS (SELECT * FROM Table_1 WHERE Id = #Id)
UPDATE Table_1 SET Name = #Name WHERE Id = #Id
ELSE
INSERT INTO Table_1 (Name) VALUES (#Name)"
Dim upsertCommand As New SqlCommand(upsertSql, connection)
upsertCommand.Parameters.Add("#Id", SqlDbType.Int, 0, "Id")
upsertCommand.Parameters.Add("#Name", SqlDbType.VarChar, 50, "Name")
adapter.InsertCommand = upsertCommand
table = New DataTable()
End Sub
Private Sub GetSchema()
adapter.FillSchema(table, SchemaType.Source)
BindingSource1.DataSource = table
DataGridView1.DataSource = BindingSource1
End Sub
Private Sub SaveData()
Validate()
BindingSource1.EndEdit()
adapter.Update(table)
End Sub
The SQL for the insert and update goes in the InsertCommand because all the DataRows in the DataTable will have a RowState of Added, so the InsertCommand will be executed for each one. In this example, I have called FillSchema to create a DataTable with a schema that matches the database but with no rows. You can create your DataTable however is appropriate.
I can't fully answer this, because you didn't show us a way to run an SQL query on your database that correctly handles parameters. The code you have, including the ExecuteSQL() method, is horribly broken, and will fail any time a name or abbreviation has, for example, a single quote as part of the value.
Of course, you could escape for that... but that's just one way of several user input could break your SQL. Worse, malicious users can use this to cause very bad things to happen in your database.
So instead, I've written this out showing some good practices, including parameterized queries and an all-sql upsert. You'll have to fill in the connection string and correct column information. Moreover, you need to adopt this pattern throughout your application! Yes, that will mean updating the ExecuteSQL() method.
THIS STUFF IS IMPORTANT!
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SQL As STring = _
"BEGIN TRY
INSERT INTO TBL_Stream (Name, Abbrev) VALUES (#Name, #Abbrev);
END TRY
BEGIN CATCH
-- ignore duplicate key errors, throw the rest.
IF ERROR_NUMBER() IN (2601, 2627)
UPDATE TBL_Stream
SET Abbrev = #Abbrev
WHERE Name = #Name;
END CATCH"
Using cn As New SqlConnection(" connection string here "), _
cmd As New SqlCommand(SQL, cn)
'I have to guess at type and length. You should use the actual type and length from the database
Dim name As SqlParameter = cmd.Parameters.Add("#Name", SqlDbType.NVarChar, 50)
Dim abbrev As SqlParameter = cmd.Parameters.Add("#Abbrev", SqlDbType.NVarChar, 10)
cn.Open()
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
name.Value = row.Cells(0).Value
abbrev.Value = row.Cells(1).Value
cmd.ExecuteNonQuery()
End If
Next row
End Using
GetGrid()
MsgBox("Record Saved", MsgBoxStyle.Information, "Saved")
End Sub
Now let's work on updating things to better support this throughout your application.
First, make a new Module. We'll move things there so we can enforce all database access goes through our new, safe pattern. Then, we can make our new method private within the module, which will further reduce temptation to write bad queries. Finally, each query you need to run will get it's own public method in the Module. Now, accessing your database will look more like calling regular methods.
Here's what I came up with. There are (so far) three members of this module. Take care to note the Public vs Private choices, because those are important for achieving all the goals here:
Public Module DB
Private Property ConnectionString As String = " connection string here "
Private Function ExecuteSQL(SQL As String, Params Parameters() As SqlParameter) As DataTable
Dim result As New DataTable
'Because of connection pooling it really is better to create a new connection object in most circumstances.
'Don't try to reuse the same connection throughout your app!
Using cn As New SqlConnection(ConnectionString), _
cmd As New SqlCommand(SQL, cn)
If Parameters IsNot Nothing Then
cmd.Parameters.AddRange(Parameters)
End If
cn.Open()
Using rdr As SqlDataReader = cmd.ExecuteReader()
result.Load(rdr)
Return result
End Using
End Using
End Function
'This is just one way to build this method.
' The important thing is all methods here are encouraged to use good parameterization
Public Sub UpsertStream(Name As String, Abbrev As String)
Dim SQL As STring = _
"BEGIN TRY
INSERT INTO TBL_Stream (Name, Abbrev) VALUES (#Name, #Abbrev);
END TRY
BEGIN CATCH
-- ignore duplicate key errors, throw the rest.
IF ERROR_NUMBER() IN (2601, 2627)
UPDATE TBL_Stream
SET Abbrev = #Abbrev
WHERE Name = #Name;
END CATCH"
Dim n As New SqlParameter("#Name", SqlDbType.NVarChar, 50).Value = Name
Dim a As New SqlParameter("#Abbrev", SqlDbType.NVarChar, 10).Value = Abbrev
ExecuteSQL(SQL, n, a)
End Sub
End Module
And here's how to use it with the Button_Click() method:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
DB.UpsertStream(row.Cells(0).Value, row.Cells(1).Value)
End If
Next row
GetGrid()
MsgBox("Record Saved", MsgBoxStyle.Information, "Saved")
End Sub
As the application grows, you could eventually move this module to it's own class library project, where the Module and the ExecuteSQL() method as declared as Friend instead of Public or Private. Then you can also move the numerous Public methods into other new Public Modules within that class library, to get logical groupings between feature areas.

Why doesn't this code run on Form Load, and only on button click?

I have tried form show,activate,load none work. The only way I can get this code to work is upon a button click. Is there anyway to automate the btnclick? Possibly we can figure out why this code doesn't work on form load.
A little context here, I'm have a user enter in a new job and I've loaded values entered into the previous form, to be displayed at the top of the current form. It works, just on button click. Why? Any ideas? BTW Activated below throws it into a infinite loop.
Public Class Vinyl
Dim jobnumber As Integer
Sub New()
InitializeComponent()
End Sub
'Collects the newely created job id from previous form
Public Property JobID() As Integer
Get
Return jobnumber
End Get
Set(ByVal Value As Integer)
jobnumber = Value
End Set
End Property
Dim dbInsert As New OleDb.OleDbCommand
Dim dbConnect As New OleDb.OleDbConnection
Dim Line As String = Environment.NewLine
Dim ds As New DataSet, ds2 As New DataSet
Dim da As OleDb.OleDbDataAdapter, da2 As OleDb.OleDbDataAdapter
Dim PartNumber As String, PartDescription As String
Dim PCR As Integer, run As Integer
Dim Pdescription As Object
Public Sub New(jobNum As Integer)
InitializeComponent()
jobnumber = jobNum
End Sub
Private Sub Vinyl_Load(sender As Object, e As System.EventArgs) Handles Me.Load
dbConnect.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\crabara\Desktop\Project Alpha 3\MDB.accdb;Persist Security Info=False;"
dbConnect.Open()
da = New OleDb.OleDbDataAdapter("SELECT PartNumber,PCRNumber,Run FROM Molding WHERE JobID ='" & jobnumber & "'", dbConnect)
da.Fill(ds, "Molding")
PartNumber = ds.Tables("Molding").Rows(0).Item(0)
PCR = ds.Tables("Molding").Rows(0).Item(1)
run = ds.Tables("Molding").Rows(0).Item(2)
lblPartNumber.Text = PartNumber
lblPCR.Text = PCR
lblRun.Text = run
da2 = New OleDb.OleDbDataAdapter("SELECT PartDescription FROM PART_LIST WHERE PartNumber ='" & PartNumber & "'", dbConnect)
da2.Fill(ds2, "PartDescription")
PartDescription = ds2.Tables("PartDescription").Rows(0).Item(0)
lblPartDescription.Text = Pdescription
End Sub
Private Sub InitializeComponents()
Throw New NotImplementedException
End Sub
End Class
This is the snippet of code from the previous form that is related to the jobnumber variable.
JobId2 = ds3.Tables("JobID").Rows(0).Item(0)
dbInsert.Parameters.Add(dbInsert.CreateParameter).ParameterName = "JobID"
dbInsert.Parameters.Item("JobID").Value = JobId2
'Add Values into Vinyl DB
dbInsert.CommandText = "INSERT INTO Molding(PartNumber,PCRNumber,Run,JobNo,JobID) VALUES(txtPart.Text,pcr,run,txtJobNo.Text,JobId2);"
dbInsert.CommandType = CommandType.Text
dbInsert.Connection = dbConnect
dbInsert.ExecuteNonQuery()
'Loads the newly created jobid into the vinyl form
myForm2.JobID = JobId2
myForm2.Show()
I think I figured this out. You are relying on the JobNumber variable in your code, but that looks like it isn't set until after the form is loaded. Since it's zero, your queries are coming back empty and since your code is simply assuming there are records, you get an exception when you try to access a row or a column that doesn't exist.
If the JobNumber variable is critical to the form, try passing it through the constructor:
Public Sub New(jobNum As Integer)
InitializeComponent()
jobnumber = jobNum

Why i can not use string dataType as input argument in webmethod in vb.net

i implemented a webservice with vb.net
method is like this
Public Class WebService
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function INSERT_NEW(ByVal i As Integer, ByVal f As String) As String
Dim con As New OleDbConnection
Dim cmd As New OleDbCommand
Try
con.ConnectionString = ConfigurationManager.ConnectionStrings("WebConnectionSTR").ToString
'Dim strMdbPath As String = "C:\Users\Hossein\Documents\Visual Studio 2010\WebSites\WebSite1\"
'Dim strProvider As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
'Dim strDBFile As String = "db.mdb"
cmd.Connection = con
cmd.CommandText = "insert into tb values (" & i & ",'" & f & "')"
con.Open()
cmd.ExecuteNonQuery()
con.Close()
Return "1"
Catch ex As Exception
con.Close()
Return "0"
End Try
End Function
End Class
it works if i run it and invoke it
but when i create a windows application i occured with an unkown problem
because i used 2 (integer and string) input parameters in web method as input parameters,
INSERT_NEW(byval i as integer,byval f as string) as string
it didnt work
Imports wsdl.Myservice
Public Class Form1
Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
Dim s As WebServiceSoap = New WebServiceSoapClient
lblAdd.Text = s.INSERT_NEW(txt1.Text, txt2.Text)
End Sub
End Class
but when i change the input argument in web method to INTEGER it works properly
is it a limitation to use data types in web method in web service OR i did something wrong???
i added these 3 photos to show you the exact error that i get.
You declare your webmethod to receive an Integer and a String. So you should pass an Integer and a String, but your code tries to pass two strings. You should respect the signature of the webmethod and pass the parameters as expected
lblAdd.Text = s.INSERT_NEW(Convert.ToInt32(txt1.Text), txt2.Text)
Of course, here I am assuming that the string in txt1.Text is convertible in an integer.
Said that I wish to point your attention to a very big problem of your code:
What happen if a malicious user pass for the parameter f the following string
"xxxxx');DELETE FROM tb; --"
It is called Sql Injection and could wreak havoc with your database. Try to use ALWAYS a parameterized query when you receieve input from your users and pass it to a database command
Using con = New OleDbConnection(ConfigurationManager.ConnectionStrings("WebConnectionSTR").ConnectionString)
Using cmd = New OleDbCommand("insert into tb values (?, ?)", con)
Try
con.Open()
cmd.Parameters.AddWithValue("#p1",i)
cmd.Parameters.AddWithValue("#p2",f)
cmd.ExecuteNonQuery()
Return "1"
Catch ex As Exception
Return "0"
End Try
End Using
End Using
Finally i found the answer myself
Imports wsdl.Myservice
Imports System.Reflection
Public Class Form1
Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
Dim s As WebServiceSoap = New WebServiceSoapClient
Dim method As MethodInfo = s.GetType().GetMethod("INSERT_NEW")
Dim returnValue As Integer = method.Invoke(s, New Object() {CInt(txt1.Text), txt2.Text})
lblAdd.Text = returnValue
End Sub
End Class

vb.net login control not re-authenticating

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.)