Insert asp.net Membership-generated UserId into custom table (vb) - asp.net

I've spent a couple of hours trying to find the answer to this, and although there are tutorials all over the 'net none of them work for me (or I am too n00b to understand what they're telling me...)
Anyway, I'm creating users in asp.net using Membership. What I want to do is add the generated UserId to a column in a custom table I've created, to link the stuff in the custom table with the user created in aspnet_Users.
Here's the code I've got for the registration submit button:
Private Sub submit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles submit.Click
Dim connectionString As String = WebConfigurationManager.ConnectionStrings("edinsec").ConnectionString
Dim createStatus As MembershipCreateStatus
Membership.CreateUser(fname.Text, password.Text, email.Text, sq.Text, sa.Text, False, createStatus)
''#Something has to happen here!
Dim insertSQL As String
insertSQL = "INSERT INTO clients (UserId)"
insertSQL &= "VALUES (#userId)"
Using con As New SqlConnection(connectionString)
Dim cmd As New SqlCommand(insertSQL, con)
cmd.Parameters.AddWithValue("#firstname", firstname.Text)
Try
Try
con.Open()
Catch ex As SqlException
MsgBox("Connection Problem - Please Retry Later", 65584, "Connection Error")
End Try
cmd.ExecuteNonQuery()
MsgBox("Thank you for joining us - we will be in touch shortly.", 65600, "Join Up")
Response.Redirect("Default.aspx")
Catch Err As SqlException
MsgBox("Error inserting record - please retry later.", 65584, "Insertion Error")
End Try
con.Close()
End Using
End Sub
As you can see I'm trying to grab the Membership-generated userid and insert it into the clients table. I've tried numerous approaches to grabbing the UserId but none work.
Membership works to create the user, it's just the part afterwards that I'm stuck on.
Any help would be much appreciated :)

I managed it in the end using this code:
Dim userid As Guid = New Guid(Membership.GetUser(username.Text).ProviderUserKey.ToString())
...where username.Text is the content of the username form input, where the user chooses their username.
The relevant parameter line is this:
cmd.Parameters.Add("#UserId", g)
I get a warning about the method I'm using being deprecated, but it works at least!

Membership.CreateUser returns a MembershipUser object. You can get the UserId from that returned object.
MembershipUser user = Membership.CreateUser(...);
Guid userId = (Guid)user.ProviderUserKey;

Related

show user's details from table on aspx when logged in

I posted a similar question previously but quickly deleted it as the question had a number of errors and was not clear for readers.
I am creating a log in for a patient and when logged in (from the log in page login.aspx) I want them to be redirected to a page (in this case user.aspx) when the log in is authenticated and show their details from a table.
So far I can just get a label to provide user logged in correct or user log in incorrect.
I have a patient table as follows - this is all dummy data and made up user/accounts:
This is the code behind file, have I set a session correctly? and how when the user is authenticated can they be redirected to user.aspx with their corresponding details from a table (for instance their user details)
Imports System.Data.SqlClient
Imports System.Data
Partial Class Pages_Login
Inherits System.Web.UI.Page
Protected Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
Dim patientNo As String
Dim password As String
Dim bAuthethicated As Boolean
patientNo = txtuser.Text
password = txtpassword.Text
bAuthethicated = CheckUser(patientNo, password)
If bAuthethicated Then
lblresult.Text() = "correct"
Else
lblresult.Text() = "Incorrect Student Number and/or Password"
End If
End Sub
Public Function CheckUser(patientNo As String, password As String) As Integer
Dim cmdstring As String = "SELECT * FROM Patient Where Username=#PATIENTNO AND Password=#PASSWORD"
Dim found = 0
Using conn As New SqlConnection("Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\Laura\Final_proj\App_Data\surgerydb.mdf;Integrated Security=True;Connect Timeout=30")
Dim cmd = New SqlCommand(cmdstring, conn)
cmd.Parameters.Add("#PATIENTNO", SqlDbType.NChar).Value = patientNo
cmd.Parameters.Add("#PASSWORD", SqlDbType.NChar).Value = password
conn.Open()
Dim reader = cmd.ExecuteReader()
While reader.Read()
Session("PatientId") = CInt(reader.Item("PatientId"))
found = CInt(reader.Item("PatientId"))
End While
reader.Close()
End Using
Return (found)
End Function
End Class
I hope someone can help. If I can provide any more information or direction on the question please let me know.
Rather than showing the user that they have successfully logged in, just add the following line of code to redirect them to the user.aspx page:
Response.Redirect("user.aspx", True)
On the user page, you need to check if the Session("PatientId") is empty, if so, then redirect back the login page. If it does have a value, ensure it is a number and then use it to load up the patient details with another DB call.
Also another tip, I noticed your passwords are in plain text. I would highly recommend that you one-way hash them using a simple function for additional security. You can then use the same function to hash the password used on the login page to compare against the database value.

Error: "No value given for one or more required parameters" on UPDATE query from ASP.NET

I receive the error
No value given for one or more required parameters
when I try to execute the following code
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim t2 = TextBox2.Text
Dim dbcmd As OleDbCommand
dbcmd = New OleDbCommand("UPDATE login1 SET height ='" + TextBox2.Text + "' WHERE username =" + str, dbcon) //This is the part where the error is ....
dbcon.Open()
dbcmd.ExecuteNonQuery()
dbcon.Close()
End Sub
End Class
I've tried making changes in this statement like using different methods with parameters...but all the code shows the same error.
Using a parameterized query is definitely the way to go, but using named parameters should be discouraged in this context because OleDbCommand objects ignore the parameter names when the CommandType is Text. They only rely on the order in which the parameters appear in the CommandText (ref: here).
Therefore, the preferred approach would be
Using dbcmd As New OleDbCommand(
"UPDATE login1 SET height=? WHERE username=?",
dbcon)
dbcmd.Parameters.AddWithValue("?", TextBox2.Text) ' height
dbcmd.Parameters.AddWithValue("?", str) ' username
dbcmd.ExecuteNonQuery()
End Using
You don't supply the user name properly at the end of the query. But that's not the only problem here. Let me edit the code a bit:
Using dbcon As New OleDbConnection(cString)
dbcon.Open()
Using dbcmd As New OleDbCommand(
"UPDATE login1 SET height = #height WHERE username = #username",
dbcon)
dbcmd.Parameters.AddWithValue("#height", TextBox2.Text)
dbcmd.Parameters.AddWithValue("#username", str)
dbcmd.ExecuteNonQuery()
End Using
End Using
NOTE: the using statement to ensure the objects are disposed property and also, do not share connections. When you need a connection, build it, open it, use it, and dispose it.

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

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

Evaluating whether a page is the result of a referral from a particular page

I have an Edit Profile page which allows users to change their information - currently it only allows users who have a record in the table 'userprofiles' to edit their information. I want newly registered users to be able to edit their profiles as well.
At the minute, I am using the ASP.NET membership system with the appropriate asp.net_ tables in an Access database to store user credentials. The 'userprofiles' table is a separate table which has more personal information in it. There is no link between the two tables
Here is my code behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsCrossPagePostBack Then
SeparateNewUserFunction()
Return
End If
If Not IsPostBack Then
DisplayData()
SaveConfirmation.Visible = False
End If
End Sub
And here is my DisplayData() function just if anyone was interested as to what it does:
Protected Sub DisplayData()
Dim conn As OleDbConnection = New OleDbConnection(ConfigurationManager.ConnectionStrings("BookMeetConnString").ConnectionString)
Dim sql = "SELECT * FROM userprofiles WHERE TravellerName=#f1"
Dim cmd = New OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("#f1", User.Identity.Name)
conn.Open()
Dim profileDr = cmd.ExecuteReader()
profileDr.Read()
Dim newEmailAddress = ""
Dim newDescription = ""
If Not IsDBNull(profileDr("EmailAddress")) Then newEmailAddress = profileDr.Item("EmailAddress")
If Not IsDBNull(profileDr("Description")) Then newDescription = profileDr.Item("Description")
If Not IsDBNull(profileDr("AvatarURL")) Then ProfilePic.ImageUrl = profileDr.Item("AvatarURL")
description.Text = newDescription
email.Text = newEmailAddress
conn.Close()
End Sub
Rather than checking if a record exists in the 'userprofiles' table that matches the User.Identity.Name of the current user, I thought it would be easier just to evaluate whether or not the user had just been redirected from the Register.aspx page. (If this evaluation is true, then as you can see above, a separate "New User" function will be called).
That is my logic, but I have no clue if VB.NET has a "referrer" or "isReferred" expression? (at the minute as you can see I thought isCrossPagePostback might be the right thing but no luck!)
Any ideas?
You need to check whether or not a record exists and base your logic on that. That is the only right way to do it. As in:
What if you introduce a new page to handle registrations? This logic breaks.
What if you one day you retire and the next guy decides to rename the Register.aspx page? This logic breaks.
What if user hits back button and clicks the Register button again? This logic may break.
You should also consider a foreign key and unique constraint on that table, as well as using UserId instead of TravellerName. TravellerName can change, UserId will not.
... and yes you can the referring page by using HttpRequest.ServerVariables, which gets you a list of IIS Server Variables.

How can I make the logged-In name the default option in dropdownlist box?

Experts.
When a user logs into one of our web apps, there is a dropdownlist containing the names of all of our employees.
An employee could log into the system to record his or her entries into the database.
The employee could log the entries for another employee.
So far, an employee has had to select his or her name from the dropdown list and we don't want employees typing their names, just for consistency and to preserve data integrity.
Our problem currently is how to have employee's login name become the default option in the dropdown. The employee can select another name from the list if making the entries for another empployee.
Any ideas how to accomplish this task?
Thanks alot in advance.
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Dim s As String
Dim reader As OleDbDataReader
txtFullName.Text = Session.Item("assignedTo").ToString
'Initialize Connection
s = "Select login_id, UserName from tblusers ORDER BY UserName"
Dim connStr As String = ConfigurationManager.ConnectionStrings("allstringconstrng").ConnectionString
Dim conn As New OleDbConnection(connStr)
Dim cmd As New OleDbCommand(s, conn)
'Open the connection
conn.Open()
Try
'Execute the Login command
reader = cmd.ExecuteReader()
'Populate the list of Users
txtLoginName.DataSource = reader
txtLoginName.DataValueField = "login_id"
txtLoginName.DataTextField = "UserName"
txtLoginName.DataBind()
'Close the reader
reader.Close()
Finally
'Close Connection
conn.Close()
End Try
End If
End Sub
<--new code -->
Try
'Execute the Login command
reader = cmd.ExecuteReader()
'Populate the list of Users
Dim currentUserName As String = ""
While reader.Read()
If (reader("login_id").ToString().Equals(currentUserName)) Then
currentUserName = reader("UserName").ToString()
End If
End While
txtLoginName.SelectedValue = currentUserName
'Close the reader
reader.Close()
Finally
'Close Connection
conn.Close()
End Try
you can use Page.User property to get the Name and then assign it to the dropdown's selected Value on Page_Load event.
Could you just simply select it by text after you populate the list? I assume you'll know the login_id once the user logs in, so you could find the username from the results of the query, like so:
UNTESTED:
string currentUserName = "";
While reader.Read()
If (reader("login_id").ToString().Equals(currentUserLogin)) Then
currentUserName = reader("UserName").ToString()
End If
End While
And then, once the list is populated via the results, select the correct user by username.
txtLoginName.Items.FindByValue(UserName).Selected = true;
Or even better yet, since you should already know the login_id, you can simply select by value from the populated drop down list, like so:
txtLoginName.SelectedValue = login_id
It's worth noting that this is making a very big assumption that the login_id will exist in the list. You may want to perform the appropriate check first to see if the login_id exists before selecting.
If you are using forms or windows authentication, wouldn't you just use:
txtLoginName.Text = User.Identity.Name
I believe this will select it if the text is in the list and matches exactly. Or, just use Sam's method. But was it the User.Identity.Name that you were looking for?

Resources