As its well known that membership create user functionality lacks a lot of user details that someone might need to store. I am presenting my work around it and I need your expert opinion, ( I am using web method)
I m currently using this code (Ref Microsoft)
Public Function GetErrorMessage(status As MembershipCreateStatus) As String
Select Case status
Case MembershipCreateStatus.DuplicateUserName
Return "Username already exists. Please enter a different user name."
Case MembershipCreateStatus.DuplicateEmail
Return "A username for that e-mail address already exists. Please enter a different e-mail address."
Case MembershipCreateStatus.InvalidPassword
Return "The password provided is invalid. Please enter a valid password value."
Case MembershipCreateStatus.InvalidEmail
Return "The e-mail address provided is invalid. Please check the value and try again."
Case MembershipCreateStatus.InvalidAnswer
Return "The password retrieval answer provided is invalid. Please check the value and try again."
Case MembershipCreateStatus.InvalidQuestion
Return "The password retrieval question provided is invalid. Please check the value and try again."
Case MembershipCreateStatus.InvalidUserName
Return "The user name provided is invalid. Please check the value and try again."
Case MembershipCreateStatus.ProviderError
Return "The authentication provider Returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator."
Case MembershipCreateStatus.UserRejected
Return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator."
Case Else
Return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator."
End Select
End Function
Public Function GetUsrID(UserName) As String
Dim sql As String = "SELECT UserId FROM aspnet_Users WHERE UserName= #UserName"
Using cn As New SqlConnection(ARTSQLDBCOM), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#UserName", SqlDbType.VarChar, 256).Value = UserName
cn.Open()
Dim val As String = String.Empty
Dim getVal As Object = cmd.ExecuteScalar()
cn.Close()
If Not IsNothing(getVal) Then
val = getVal.ToString
Return val
Else
Return Nothing
End If
End Using
End Function
Public Function CreateUser_AugmentedUpdate(ByVal UserName As String, ByVal JobTitleID As String, ByVal Prfx As String, ByVal fname As String, ByVal Mname As String, ByVal Lname As String, ByVal Initial As String, _
ByVal disname As String, ByVal UsrDOB As String, ByVal TelNum As String, ByVal UsrSignature As String, ByVal UsrImg_aURL As String, ByVal UsrImg_rURL As String)
Try
Dim UserID As String = GetUsrID(UserName)
Dim SQLCmd As New SqlCommand()
SQLCmd.CommandType = CommandType.StoredProcedure
SQLCmd.CommandText = "aspnet_Users_CreateUser_AugmentedUpdate"
SQLCmd.Parameters.Add("#UserId", SqlDbType.NVarChar).Value = UserID.ToString
If (String.IsNullOrEmpty(JobTitleID)) Then
SQLCmd.Parameters.Add("#JobTitleID", SqlDbType.Int).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#JobTitleID", SqlDbType.Int).Value = Convert.ToInt32(JobTitleID)
End If
If (String.IsNullOrEmpty(Initial)) Then
SQLCmd.Parameters.Add("#Initial", SqlDbType.Int).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#Initial", SqlDbType.Int).Value = Convert.ToInt32(Initial)
End If
If (String.IsNullOrEmpty(Prfx)) Then
SQLCmd.Parameters.Add("#Prfx", SqlDbType.Int).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#Prfx", SqlDbType.Int).Value = Convert.ToInt32(Prfx)
End If
If (String.IsNullOrEmpty(fname)) Then
SQLCmd.Parameters.Add("#fname", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#fname", SqlDbType.NVarChar).Value = fname.ToString
End If
If (String.IsNullOrEmpty(Mname)) Then
SQLCmd.Parameters.Add("#Mname", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#Mname", SqlDbType.NVarChar).Value = Mname.ToString
End If
If (String.IsNullOrEmpty(Lname)) Then
SQLCmd.Parameters.Add("#Lname", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#Lname", SqlDbType.NVarChar).Value = Lname.ToString
End If
If (String.IsNullOrEmpty(disname)) Then
SQLCmd.Parameters.Add("#disname", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#disname", SqlDbType.NVarChar).Value = disname.ToString
End If
Dim dateValue As Date
If String.IsNullOrWhiteSpace(UsrDOB) Then
SQLCmd.Parameters.Add("#UsrDOB", SqlDbType.Date).Value = DBNull.Value
ElseIf Date.TryParse(UsrDOB, dateValue) Then
SQLCmd.Parameters.Add("#UsrDOB", SqlDbType.Date).Value = dateValue
Else
SQLCmd.Parameters.Add("#UsrDOB", SqlDbType.Date).Value = DBNull.Value
End If
If (String.IsNullOrEmpty(TelNum)) Then
SQLCmd.Parameters.Add("#TelNum", SqlDbType.NChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#TelNum", SqlDbType.NChar).Value = TelNum.ToString
End If
If (String.IsNullOrEmpty(UsrSignature)) Then
SQLCmd.Parameters.Add("#UsrSignature", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#UsrSignature", SqlDbType.NVarChar).Value = UsrSignature.ToString
End If
If (String.IsNullOrEmpty(UsrImg_aURL)) Then
SQLCmd.Parameters.Add("#UsrImg_aURL", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#UsrImg_aURL", SqlDbType.NVarChar).Value = UsrImg_aURL.ToString
End If
If (String.IsNullOrEmpty(UsrImg_rURL)) Then
SQLCmd.Parameters.Add("#UsrImg_rURL", SqlDbType.NVarChar).Value = DBNull.Value
Else
SQLCmd.Parameters.Add("#UsrImg_rURL", SqlDbType.NVarChar).Value = UsrImg_rURL.ToString
End If
SQLCmd.Connection = ARTSQLCON
ARTSQLCON.Open()
SQLCmd.ExecuteNonQuery()
ARTSQLCON.Close()
Return "User has been Created Successfully"
Catch
Return "Create User Phase 2 Error. Please refer to your database developer"
End Try
End Function
<WebMethod()> _
Public Function RegNewUser(ByVal Username As String, ByVal Password As String, ByVal Email As String, ByVal JobTitleID As String, ByVal Prfx As String, ByVal fname As String, ByVal Mname As String, ByVal Lname As String, ByVal Initial As String, _
ByVal disname As String, ByVal UsrDOB As String, ByVal TelNum As String, ByVal UsrSignature As String, ByVal UsrImg_aURL As String, ByVal UsrImg_rURL As String) As String
Dim status As MembershipCreateStatus
'Dim passwordQuestion As String = ""
'Dim passwordAnswer As String = ""
'If Membership.RequiresQuestionAndAnswer Then
' passwordQuestion = PasswordQuestionDDl.Text.Trim()
' passwordAnswer = PasswordAnswerTextbox.Text
'End If
Try
Dim newUser As MembershipUser = Membership.CreateUser(Username, Password, Email, Nothing, Nothing, False, status)
If newUser Is Nothing Then
Return GetErrorMessage(status)
Else
CreateUser_AugmentedUpdate(Username, JobTitleID, Prfx, fname, Mname, Lname, Initial, _
disname, UsrDOB, TelNum, UsrSignature, UsrImg_aURL, UsrImg_rURL)
Return "User has been Created Successfully" + JobTitleID
End If
Catch
Return "Create User Phase 1 Error. Please refer to your database developer"
End Try
End Function
Now behind this code, I put a trigger on the asp users table to insert the new userID in a different table. My SQL stored procedure (aspnet_Users_CreateUser_AugmentedUpdate) run a record update on the new table,
The code works beautifully but is it a good practice?
Thanks
Your implementation is correct, since we could not use Transaction in Membership Provider.
You will need to make sure user enters valid data before calling Membership.CreateUser. So I'll do some type of validations before that line. Otherwise, you will end up with dangling data.
Just a minor improvement which is not related to Membership. If you pass more than 3 arguments to a method, you might want to consider using object. You can read more at Clean Code by Robert C. Martin.
Public Function CreateUser_AugmentedUpdate(ByVal user As UserModel)
You can use ternary operator to shorten if statement.
SQLCmd.Parameters.Add("#TelNum", SqlDbType.NChar).Value =
If(String.IsNullOrEmpty(TelNum), DBNull.Value, TelNum.ToString)
Related
Here is whats happening , If the user is logged in - this is called directly from Page_Load
Protected Sub EnterNewTransInDb()
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("connstring").ConnectionString)
Dim comm As New SqlCommand("INSERT INTO tblRegisterRedirect (RegID , UserID, EventID, TimeStamp) VALUES (#RegID, #UserID, #EventID , getdate()) ;", conn)
Dim RegID As Guid
RegID = Guid.NewGuid()
Dim GIUDuserid As Guid
GIUDuserid = New Guid(HttpContext.Current.Request.Cookies("UserID").Value.ToString())
Dim GIUDevnetid As New Guid(HttpContext.Current.Request.QueryString("id").ToString())
comm.Parameters.AddWithValue("#RegID", RegID)
comm.Parameters.AddWithValue("#UserID", GIUDuserid)
comm.Parameters.AddWithValue("#EventID", GIUDevnetid)
Try
conn.Open()
Dim i As Integer = comm.ExecuteNonQuery()
conn.Close()
Catch ex As Exception
Dim errors As String = ex.ToString()
End Try
Dim URL As String = Request.QueryString("url").ToString()
Response.Redirect(URL + "?aid=854&rid=" + RegID.ToString())
End Sub
This works great, but if their not logged in , then they enter their log-in credentials - this happens on Button_Click event, in the click event I call this function EnterNewTransInDb() , When I run it this time , after logging in - SAME CODE , it throws an exception - Object reference is null - referring to the querystring
Protected Sub btnLogin_Click(sender As Object, e As System.EventArgs) Handles btnLogin.Click
'took out code SqlConnection onnection and SqlDataReader Code
dbCon.Open()
'If Email and PW are found
If dr.Read Then
Dim appCookie As New HttpCookie("UserID")
appCookie.Value = dr("GUID").ToString()
appCookie.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie)
Dim appCookie1 As New HttpCookie("UserName")
appCookie1.Value = dr("UserName").ToString
appCookie1.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie1)
Dim appCookie2 As New HttpCookie("UserEmail")
appCookie2.Value = txtEmail.Text.ToLower()
appCookie2.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie2)
Dim appCookie3 As New HttpCookie("Lat")
appCookie3.Value = dr("GeoLat").ToString()
appCookie3.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie3)
Dim appCookie4 As New HttpCookie("Long")
appCookie4.Value = dr("GeoLong").ToString()
appCookie4.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie4)
Dim appCookie5 As New HttpCookie("City")
appCookie5.Value = dr("City").ToString()
appCookie5.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie5)
Dim appCookie6 As New HttpCookie("State")
appCookie6.Value = dr("State").ToString
appCookie6.Expires = DateTime.Now.AddDays(30)
HttpContext.Current.Response.Cookies.Add(appCookie6)
HttpContext.Current.Response.Cookies("EO_Login").Expires = Now.AddDays(30)
HttpContext.Current.Response.Cookies("EO_Login")("EMail") = txtEmail.Text.ToLower()
Dim sUserData As String = HttpContext.Current.Server.HtmlEncode(HttpContext.Current.Request.Cookies("UserID").Value) & "|" & HttpContext.Current.Server.HtmlEncode(HttpContext.Current.Request.Cookies("UserName").Value) & "|" & HttpContext.Current.Server.HtmlEncode(HttpContext.Current.Request.Cookies("UserEmail").Value)
' Dim sUserData As String = "dbcf586f-82ac-4aef-8cd0-0809d20c70db|scott selby|scottselby#live.com"
Dim fat As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, _
dr("UserName").ToString, DateTime.Now, _
DateTime.Now.AddDays(6), True, sUserData, _
FormsAuthentication.FormsCookiePath)
Dim encTicket As String = FormsAuthentication.Encrypt(fat)
HttpContext.Current.Response.Cookies.Add(New HttpCookie(FormsAuthentication.FormsCookieName, encTicket))
'If Email and Pw are not found
Else
dr.Close()
dbCon.Close()
End If
'Always do this
dr.Close()
sSql = "UPDATE eo_Users SET LastLogin=GETUTCDATE() WHERE GUID=#GUID; "
cmd = New SqlCommand(sSql, dbCon)
cmd.Parameters.AddWithValue("#GUID", HttpContext.Current.Session("UserID"))
cmd.ExecuteNonQuery()
dbCon.Close()
EnterNewTransInDb()
'Dim URL As String = Request.QueryString("url").ToString()
'Response.Redirect(URL + "?aid=854&rid=" + RegID.ToString())
End Sub
Assuming you only want this code to run if there is a valid QueryString, you could put a guard clause at the beginning of the method to simply check if QueryString is null and then perform some other action if this page is called without a QueryString.
Try setting the breakpoints before the call and make sure the variables are assigned values.
Have you tried putting a breakpoint on Dim URL As String = Request.QueryString("url").ToString() line in your code? Maybe you just need to evaluate first the querystring for the 'url' parameter, if it exists; before converting it to a string.
Hoping for a quick answer here.
OK, since I do a lot of single value lookups from the DB, I created a function to handle the lookup for me. It's designed to get any type of data type (string, integer, date, ...).
It works when I want to retrieve a number, but gives me an error when I want a string (InvalidCastException trying to convert a string to an integer on the line: GetValue = DR(0)).
I can't do a ctype or directcast because the datatype is unknown and varies.
Haven't tested any other data types yet.
Code is below. I'd like to find out how to make this function work, or pointed to another function that will serve the same purpose.
Public Shared Function GetValue(Optional ByVal SQL As String = "", Optional ByVal FieldName As String = "", Optional ByVal TableName As String = "", Optional ByVal WhereClause As String = "") As VariantType?
Dim myConnection As SqlConnection
Dim myCommand As SqlCommand
Dim strSQL As New SQLStringBuilder
Dim DR As SqlDataReader
myConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("ConnAFRAMSSQL").ConnectionString)
strSQL.Add(SQL)
If FieldName > "" Then
strSQL.Add("SELECT " & FieldName)
End If
If TableName > "" Then
strSQL.Add("FROM " & TableName)
End If
If WhereClause > "" Then
strSQL.Add("WHERE " & WhereClause)
End If
myConnection.Open()
myCommand = New SqlCommand(strSQL.ToString, myConnection)
DR = myCommand.ExecuteReader()
If DR.HasRows Then
DR.Read()
GetValue = DR(0)
Else
GetValue = Nothing
End If
End Function
Thanks.
You may specify the System.Object (System.Object is the ultimate base class of all types) return type of your method.
Public Shared Function GetValue(Optional ByVal SQL As String = "", Optional ByVal FieldName As String = "", Optional ByVal TableName As String = "", Optional ByVal WhereClause As String = "") As Object
Dim myConnection As SqlConnection
....
Dim obj as Object=Nothing
If DR.Read()
obj=DR(0)
End If
DR.Close()
myConnection.Close()
return obj
End Function
Current issue: when running the asmx file locally to check it's working, the error that keeps coming up is that no value given as can be seen below. I've added in parameters now but the error is still appearing.
However now, I feel that the error isn't in the asmx as people have changed the SQL to run correctly. This is the aspx file where the required information is being passed over. Is it possible that there is an issue with passing the session variables that are set up?
Dim Secure As New Visa.VISAServices()
Dim authHeader As New Visa.AuthenticationHeader()
authHeader.username = "HSBC"
authHeader.password = "password"
Secure.AuthenticationHeaderValue = authHeader
Session("sessionsortnum") = sortnum.Text
Session("sessionaccount") = account.Text
'Change type for the sortcode
Dim sortcode As String = CType(Session.Item("sessionsortnum"), String)
Dim accountnumber As String = CType(Session.Item("sessionaccount"), String)
lblVisa.Text = Secure.AuthenticateCardSecure(pin.Text, sortnum.Text, account.Text)
'NEEDS TO STAY HERE DO NOT MOVE!
Session("sessioncase") = lblVisa.Text
Dim selectcase As String = CType(Session.Item("sessioncase"), String)
'Tests - Being sent to the session var
testsort.Text = sortcode
testbank.Text = accountnumber
testselectc.Text = selectcase
This is how the sessions are being passed from one service that is being connected to and the sortcode, accountnumber and selectcase are all displaying correctly.
This is the file that is calling the asmx:
Private Sub checkbalance(ByVal sender As Object, ByVal e As System.EventArgs)
Dim sortcode As String = CType(Session.Item("sessionsortnum"), String)
Dim accountnumber As String = CType(Session.Item("sessionaccount"), String)
Dim selectcase As String = CType(Session.Item("sessioncase"), String)
testsort.Text = sortcode
testbank.Text = accountnumber
testselectc.Text = selectcase
Select Case testselectc.Text
Case "1111111111"
'Dim lloydsbalance As New Lloyds.
'screen.Text = lloydsbalance.overdraft(accountnumber)
Case "2222222222"
Dim barclaysbalance As New Barclays.Transactions()
screen.Text = barclaysbalance.overdraft(accountnumber, sortcode)
Case "3333333333"
Dim santanderbalance As New Santander.Santander()
screen.Text = santanderbalance.overdraft(accountnumber, sortcode)
Case "4444444444"
Dim HSBCbalance As New HSBC.HSBC()
screen.Text = HSBCbalance.OverDraft(accountnumber)
Case "5555555555"
Dim halifaxbalance As New Halifax.Halifax()
screen.Text = halifaxbalance.overdraft(accountnumber)
Case "6666666666"
Dim natwestbalance As New Natwest.natwest()
screen.Text = natwestbalance.overdraft(accountnumber, sortcode)
End Select
End Sub
Original issue: Whenever I run the asmx locally just to check if it is working, I just get an error. I've checked the function I'm invoking, however I can't find the error. I am hoping someone can spot what I have done wrong.
Error:
System.Data.OleDb.OleDbException: No value given for one or more
required parameters. at
System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult
hr) at
System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS
dbParams, Object& executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object&
executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior
behavior, Object& executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior
behavior, String method) at
System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
at HSBC.over(Int64 accountnumber) at HSBC.OverDraft(Int64
accountnumber)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Overdraft Call
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<WebMethod()> Public Function OverDraft(ByVal accountnumber As Long) As String
Return over(accountnumber)
End Function
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Overdraft function
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Creates a service web method
Private Function over(ByVal accountnumber As Long) As String
'Open the connection to the database
Dim BalanceDr As OleDbDataReader
Dim connectioncmd As OleDbCommand
Dim connection As OleDbConnection
Dim connx As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("../database/HSBc.mdb") & ";"
Dim SQL As String = "SELECT Customer_Overdraft FROM Customer WHERE Account_Number=?"
Dim overdraft As String
connection = New OleDbConnection(connx)
connectioncmd = New OleDbCommand(SQL, connection)
connection.Open()
'Create a DataReader that will return information.
BalanceDr = _
connectioncmd.ExecuteReader(CommandBehavior.CloseConnection)
If BalanceDr.Read() Then
'A row was returned
overdraft = BalanceDr(0)
Else
'A row was not returned
overdraft = "No Balance For Account Found"
End If
BalanceDr.Close()
Return overdraft
End Function
accountnumber is stored in a session that was brought back from a service created by someone else, I know this is getting passed correctly as on ever page I check that it is the correct one being sent and used.
Anyone have any suggestions? I have also added all the required permissions to the database as well.
You need to set the command's parameter to your accountnumber that is passed in:
connectioncmd = New OleDbCommand(Sql, connection)
Dim p As OleDb.OleDbParameter = connectioncmd.CreateParameter()
p.Value = accoutnumber
connectioncmd.Parameters.Add(p)
Very close; your query:
"SELECT Customer_Overdraft FROM Customer WHERE Account_Number=?"
Is a parameterized query; you therefore need to add an OleDbParameter to your command object.
Your function should then be similar to (not near Visual Studio so can't syntax check):
Private Function over(ByVal accountnumber As Long) As String
'Open the connection to the database
Dim BalanceDr As OleDbDataReader
Dim connectioncmd As OleDbCommand
Dim connection As OleDbConnection
Dim connx As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("../database/HSBc.mdb") & ";"
Dim SQL As String = "SELECT Customer_Overdraft FROM Customer WHERE Account_Number=?"
Dim overdraft As String
connection = New OleDbConnection(connx)
connectioncmd = New OleDbCommand(SQL, connection)
'Add A Parameter!
connectioncmd.Parameters.AddWithValue("accnumber", accountnumber)
connection.Open()
'Create a DataReader that will return information.
BalanceDr = _
connectioncmd.ExecuteReader(CommandBehavior.CloseConnection)
If BalanceDr.Read() Then
'A row was returned
overdraft = BalanceDr(0)
Else
'A row was not returned
overdraft = "No Balance For Account Found"
End If
BalanceDr.Close()
Return overdraft
End Function
I would also suggest you use the using statement. This is especially important as you are not closing your database connection explicitly and are instead relying on the fact that the BalanceDr.Close() will be called. 'Using' will simplify this for you.
Your function would then be similar too:
Private Function over(ByVal accountnumber As Long) As String
'Open the connection to the database
Dim BalanceDr As OleDbDataReader
Dim connectioncmd As OleDbCommand
Dim connection As OleDbConnection
Dim connx As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("../database/HSBc.mdb") & ";"
Dim SQL As String = "SELECT Customer_Overdraft FROM Customer WHERE Account_Number=?"
Dim overdraft As String
Using connection = New OleDbConnection(connx)
Using connectioncmd = New OleDbCommand(SQL, connection)
'Add A Parameter!
connectioncmd.Parameters.AddWithValue("accnumber", accountnumber)
connection.Open()
'Create a DataReader that will return information.
Using BalanceDr = connectioncmd.ExecuteReader()
If BalanceDr.Read() Then
'A row was returned
overdraft = BalanceDr(0)
Else
'A row was not returned
overdraft = "No Balance For Account Found"
End If
End Using
End Using
End Using
Return overdraft
End Function
I have this code at the moment that authenticates a user and tries to retrieve the current authenticated users playlist but the request is inavlid and the error is as so
Execution of request failed:
http://gdata.youtube.com/feeds/api/users/xx_xxx_x#hotmail.com/playlists
Public Function GetRequest(ByVal username As String, ByVal password As String) As YouTubeRequest
Dim youtubeSettings = New YouTubeRequestSettings("test", DeveloperKey, username, password)
Dim youtubeRequest As New YouTubeRequest(youtubeSettings)
Return youtubeRequest
End Function
Public Function GetUserPlaylists(ByVal username As String, ByVal password As String)
Dim youtubeRequest As YouTubeRequest = Me.GetRequest(username, password)
Try
Dim userPlaylists As Feed(Of Playlist) = youtubeRequest.GetPlaylistsFeed(username)
If True Then
End If
Catch ex As Exception
End Try
End Function
Dim youtubeRequest As YouTubeRequest = Me.GetRequest(username, password)
Dim url As String = "https://gdata.youtube.com/feeds/api/users/default/playlists?v=2"
Try
Dim feedQuery As New FeedQuery(url)
Dim userPlaylists As Feed(Of Playlist) = youtubeRequest.Get(Of Playlist)(feedQuery)
If True Then
End If
Catch ex As Exception
End Try
End Function
I am trying to write some code to check the AD password age during a user login and notify them of the 15 remaining days. I am using the ASP.Net code that I found on the Microsoft MSDN site and I managed to add a function that checks the if the account is set to change password at next login. The login and the change password at next login works great but I am having some problems with the check for the password age.
This is the VB.Net code for the DLL file:
Imports System
Imports System.Text
Imports System.Collections
Imports System.DirectoryServices
Imports System.DirectoryServices.AccountManagement
Imports System.Reflection 'Needed by the Password Expiration Class Only -Vince
Namespace FormsAuth
Public Class LdapAuthentication
Dim _path As String
Dim _filterAttribute As String
'Code added for the password expiration added by Vince
Private _domain As DirectoryEntry
Private _passwordAge As TimeSpan = TimeSpan.MinValue
Const UF_DONT_EXPIRE_PASSWD As Integer = &H10000
'Function added by Vince
Public Sub New()
Dim root As New DirectoryEntry("LDAP://rootDSE")
root.AuthenticationType = AuthenticationTypes.Secure
_domain = New DirectoryEntry("LDAP://" & root.Properties("defaultNamingContext")(0).ToString())
_domain.AuthenticationType = AuthenticationTypes.Secure
End Sub
'Function added by Vince
Public ReadOnly Property PasswordAge() As TimeSpan
Get
If _passwordAge = TimeSpan.MinValue Then
Dim ldate As Long = LongFromLargeInteger(_domain.Properties("maxPwdAge")(0))
_passwordAge = TimeSpan.FromTicks(ldate)
End If
Return _passwordAge
End Get
End Property
Public Sub New(ByVal path As String)
_path = path
End Sub
'Function added by Vince
Public Function DoesUserHaveToChangePassword(ByVal userName As String) As Boolean
Dim ctx As PrincipalContext = New PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain)
Dim up = UserPrincipal.FindByIdentity(ctx, userName)
Return (Not up.LastPasswordSet.HasValue)
'returns true if last password set has no value.
End Function
Public Function IsAuthenticated(ByVal domain As String, ByVal username As String, ByVal pwd As String) As Boolean
Dim domainAndUsername As String = domain & "\" & username
Dim entry As DirectoryEntry = New DirectoryEntry(_path, domainAndUsername, pwd)
Try
'Bind to the native AdsObject to force authentication.
Dim obj As Object = entry.NativeObject
Dim search As DirectorySearcher = New DirectorySearcher(entry)
search.Filter = "(SAMAccountName=" & username & ")"
search.PropertiesToLoad.Add("cn")
Dim result As SearchResult = search.FindOne()
If (result Is Nothing) Then
Return False
End If
'Update the new path to the user in the directory.
_path = result.Path
_filterAttribute = CType(result.Properties("cn")(0), String)
Catch ex As Exception
Throw New Exception("Error authenticating user. " & ex.Message)
End Try
Return True
End Function
Public Function GetGroups() As String
Dim search As DirectorySearcher = New DirectorySearcher(_path)
search.Filter = "(cn=" & _filterAttribute & ")"
search.PropertiesToLoad.Add("memberOf")
Dim groupNames As StringBuilder = New StringBuilder()
Try
Dim result As SearchResult = search.FindOne()
Dim propertyCount As Integer = result.Properties("memberOf").Count
Dim dn As String
Dim equalsIndex, commaIndex
Dim propertyCounter As Integer
For propertyCounter = 0 To propertyCount - 1
dn = CType(result.Properties("memberOf")(propertyCounter), String)
equalsIndex = dn.IndexOf("=", 1)
commaIndex = dn.IndexOf(",", 1)
If (equalsIndex = -1) Then
Return Nothing
End If
groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1))
groupNames.Append("|")
Next
Catch ex As Exception
Throw New Exception("Error obtaining group names. " & ex.Message)
End Try
Return groupNames.ToString()
End Function
'Function added by Vince
Public Function WhenExpires(ByVal username As String) As TimeSpan
Dim ds As New DirectorySearcher(_domain)
ds.Filter = [String].Format("(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))", username)
Dim sr As SearchResult = FindOne(ds)
Dim user As DirectoryEntry = sr.GetDirectoryEntry()
Dim flags As Integer = CInt(user.Properties("userAccountControl").Value)
If Convert.ToBoolean(flags And UF_DONT_EXPIRE_PASSWD) Then
'password never expires
Return TimeSpan.MaxValue
End If
'get when they last set their password
Dim pwdLastSet As DateTime = DateTime.FromFileTime(LongFromLargeInteger(user.Properties("pwdLastSet").Value))
' return pwdLastSet.Add(PasswordAge).Subtract(DateTime.Now);
If pwdLastSet.Subtract(PasswordAge).CompareTo(DateTime.Now) > 0 Then
Return pwdLastSet.Subtract(PasswordAge).Subtract(DateTime.Now)
Else
Return TimeSpan.MinValue
'already expired
End If
End Function
'Function added by Vince
Private Function LongFromLargeInteger(ByVal largeInteger As Object) As Long
Dim type As System.Type = largeInteger.[GetType]()
Dim highPart As Integer = CInt(type.InvokeMember("HighPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
Dim lowPart As Integer = CInt(type.InvokeMember("LowPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
Return CLng(highPart) << 32 Or CUInt(lowPart)
End Function
'Function added by Vince
Private Function FindOne(ByVal searcher As DirectorySearcher) As SearchResult
Dim sr As SearchResult = Nothing
Dim src As SearchResultCollection = searcher.FindAll()
If src.Count > 0 Then
sr = src(0)
End If
src.Dispose()
Return sr
End Function
End Class
End Namespace
And this is the Login.aspx page:
sub Login_Click(sender as object,e as EventArgs)
Dim adPath As String = "LDAP://DC=xxx,DC=com" 'Path to your LDAP directory server
Dim adAuth As LdapAuthentication = New LdapAuthentication(adPath)
Try
If (True = adAuth.DoesUserHaveToChangePassword(txtUsername.Text)) Then
Response.Redirect("passchange.htm")
ElseIf (True = adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) Then
Dim groups As String = adAuth.GetGroups()
'Create the ticket, and add the groups.
Dim isCookiePersistent As Boolean = chkPersist.Checked
Dim authTicket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, _
txtUsername.Text, DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups)
'Encrypt the ticket.
Dim encryptedTicket As String = FormsAuthentication.Encrypt(authTicket)
'Create a cookie, and then add the encrypted ticket to the cookie as data.
Dim authCookie As HttpCookie = New HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
If (isCookiePersistent = True) Then
authCookie.Expires = authTicket.Expiration
End If
'Add the cookie to the outgoing cookies collection.
Response.Cookies.Add(authCookie)
'Retrieve the password life
Dim t As TimeSpan = adAuth.WhenExpires(txtUsername.Text)
'You can redirect now.
If (passAge.Days = 90) Then
errorLabel.Text = "Your password will expire in " & DateTime.Now.Subtract(t)
'errorLabel.Text = "This is"
'System.Threading.Thread.Sleep(5000)
Response.Redirect("http://somepage.aspx")
Else
Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, False))
End If
Else
errorLabel.Text = "Authentication did not succeed. Check user name and password."
End If
Catch ex As Exception
errorLabel.Text = "Error authenticating. " & ex.Message
End Try
End Sub
`
Every time I have this Dim t As TimeSpan = adAuth.WhenExpires(txtUsername.Text) enabled, I receive "Arithmetic operation resulted in an overflow." during the login and won't continue.
What am I doing wrong? How can I correct this? Please help!!
Thank you very much for any help in advance.
Vince
Ok I tried to use a different approach.
Here are the functions converted from C#:
Public Function PassAboutToExpire(ByVal userName As String) As Integer
Dim passwordAge As TimeSpan
Dim currentDate As DateTime
Dim ctx As PrincipalContext = New PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain)
Dim up = UserPrincipal.FindByIdentity(ctx, userName)
'Return (Not up.LastPasswordSet.HasValue)
'returns true if last password set has no value.
Dim pwdLastSet As DateTime = DateTime.FromFileTime(LongFromLargeInteger(up.LastPasswordSet))
currentDate = Now
passwordAge = currentDate.Subtract(pwdLastSet)
If passwordAge.Days > 75 Then
'If pwdLastSet.Subtract(passwordAge).CompareTo(DateTime.Now) > 0 Then
'Dim value As TimeSpan = pwdLastSet.Subtract(passwordAge).Subtract(DateTime.Now)
'If (value.Days > 75) Then
Return passwordAge.Days
'End If
Else
Return False
'already expired
End If
End Function
Private Function LongFromLargeInteger(ByVal largeInteger As Object) As Long
Dim type As System.Type = largeInteger.[GetType]()
Dim highPart As Integer = CInt(type.InvokeMember("HighPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
Dim lowPart As Integer = CInt(type.InvokeMember("LowPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
Return CLng(highPart) << 32 Or CUInt(lowPart)
End Function
And here is the code snippet from the logon.aspx page:
sub Login_Click(sender as object,e as EventArgs)
Dim adPath As String = "LDAP://DC=xzone,DC=com" 'Path to your LDAP directory server
Dim adAuth As LdapAuthentication = New LdapAuthentication(adPath)
Try
If (True = adAuth.DoesUserHaveToChangePassword(txtUsername.Text)) Then
Response.Redirect("http://mypass.nsu.edu")
ElseIf (adAuth.PassAboutToExpire(txtUsername.Text) > 0) Then
Response.Redirect("http://www.yahoo.com")
Now when I try to login I receive the exception error: Error authenticating. Method 'System.DateTime.HighPart' not found.
and I don't know why. Anyone has any idea?
I would use the DateDiff function to determine the remaining number of days rather than using currentDate.Subtract
Dim passwordAge As Integer = (CInt)DateDiff(DateInterval.Day, Now, up.LastPasswordSet))
That will return an integer representing the number of days between now and when the password will need to be set.