The parameterized query which was not supplied - asp.net

I keep getting this error :
The parameterized query '(#AdminEmail nvarchar(4000),#AdminPassword
nvarchar(4000))SELECT' expects the parameter '#AdminEmail', which was
not supplied.
Code:
Public Function AuthenticateAdmin() As Boolean
Dim Success As Boolean
Dim strConn As String
strConn = ConfigurationManager.ConnectionStrings("HMVDb").ToString
Dim conn As New SqlConnection(strConn.ToString())
Dim cmd As New SqlCommand("SELECT * FROM Admin WHERE AdminEmail=#AdminEmail AND Adminpassword=#Adminpassword", conn)
cmd.Parameters.AddWithValue("#AdminEmail", EMail)
cmd.Parameters.AddWithValue("#AdminPassword", Password)
Dim da As New SqlDataAdapter(cmd)
Dim ds As New DataSet
conn.Open()
da.Fill(ds, "Admin")
conn.Close()
If ds.Tables("Admin").Rows.Count > 0 Then
Dim aemail As String = ds.Tables("Admin").Rows(0).Item("AdminEmail")
Dim apass As String = ds.Tables("Admin").Rows(0).Item("AdminPassword")
Dim aid As Integer = ds.Tables("Admin").Rows(0).Item("AdminID")
Dim aname As String = ds.Tables("Admin").Rows(0).Item("AdminName")
If EMail = aemail And Password = apass Then
ID = aid ' Shopper ID that identify Ecader
Name = aname
Success = True 'Shopper is authenticated
Else
Success = False 'Authentication fail
End If
End If
'Return the authentication result to calling program
Return Success
End Function

Your #AdminEmail variable EMail is null. You cannot pass a null on a required parameter. Use DBNull.Value.
When using null, you are informing Sql Server that you are omitting the parameter. This can be useful for an optional parameter with a default value, but causes an error for a required parameter.
I recommend that you use always use a utility function when passing a value to a command parameter.
For example:
public static object GetDataValue(object value)
{
if(value == null)
{
return DBNull.Value;
}
return value;
}
and then use
cmd.Parameters.AddWithValue("#AdminEmail", GetDataValue(EMail))

Is it possible that the EMail property is null (Email is Nothing)? I think you might get that error in that case. Be sure that EMail = String.Empty or EMail = "" before you set your parameter value.
Edit: Or as another answer suggests, you can send DBNull.Value instead if you actually want nulls in your database.

Step through your code and see what the value of Email and Password are. Chances are they are null.

Related

How build Get with two parameters in Web API

I'm very confused on how to configure a Get with more than one in SQL.
the answers in the forum are very fragmented and so far I have not been able to implement a solution to the code below. I know it should not be too complicated, but I can not.
My code is the one below.
Thank you very much.
[HttpGet]
[Route("cliente/{paramOne}/{paramTwo}")]
public HttpResponseMessage GetNomeNasc(string paramOne, string paramTwo)
{
try
{
Cliente cliente = null;
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandText = "select id, nome, datanascimento, nascidoEm, email from clientes where nome =" + #paramOne + " and nascidoEm = " + #paramTwo;
command.Parameters.AddWithValue(paramOne, paramTwo);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
cliente = new Cliente()
{
Id = reader["id"] == DBNull.Value ? 0 : Convert.ToInt32(reader["id"]),
Nome = reader["nome"] == DBNull.Value ? string.Empty : reader["nome"].ToString(),
NascidoEm = reader["nascidoEm"] == DBNull.Value ? string.Empty : reader["nascidoEm"].ToString(),
DataNascimento = reader["datanascimento"] == DBNull.Value ? DateTime.MinValue : Convert.ToDateTime(reader["datanascimento"]),
Email = reader["email"] == DBNull.Value ? string.Empty : reader["email"].ToString()
};
}
}
connection.Close();
}
return Request.CreateResponse(HttpStatusCode.OK, cliente);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
}
}
Depending on the underlying Database Driver you can use either named or anonymous Parameters.
Your problem ist that you are not adding individual Parameters.AddwithValue(string name, Object object) expect a Parameter name and the value that is to be inserted. Look at the definition of this function
An even better way of doing that would be the following:
command.Parameters.Add("#paramOne", DbType, size).Value = paramOne
which you would have to adapt according to what is allowed for the individual column which the value should be added to. Look here.
For Example we want to insert into a column which expects an integer, you would have the following line
command.Parameters.Add("#paramOne", SqlDbType.Integer).Value = paramOne
Be aware that like this you have to add the Parameters individually. Depending on the Db Driver you have to do that in the order they are referenced in (Anonymous) or can be referenced by name and the order is of no concern.
You can also use the Parameters.AddRange() Function to either add an Array of values or pre-constructed SqlParameters.

Augmenting membership user creation functionality

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)

ASP IF Logic not fully functioning

I have a login form that checks for roles and when the credentials are met, the user is directed to a specific page. My issue is that when the username or password is incorrect, my logic fails to prompt the user via a label that I have in the design. I even tried implementing it via a Try/Catch and still the same result.
The Design:
<div><asp:Label ID="lblinfo" runat="server" Width="374px" CssClass="blktext"></asp:Label></div>
The code in behind the (button event-handler):
Try
Dim con As New SqlConnection(GetConnectionString())
con.Open()
Dim cmd As New SqlCommand("Check_Users", con)
cmd.CommandType = CommandType.StoredProcedure
Dim p1 As New SqlParameter("Login_name", username.Text)
Dim p2 As New SqlParameter("Login_Pwd", password.Text)
cmd.Parameters.Add(p1)
cmd.Parameters.Add(p2)
Dim rd As SqlDataReader = cmd.ExecuteReader()
'check the Role of the user logging in'
While (rd.Read())
Session("numrecord") = rd.GetValue(0).ToString()
rd.GetValue(11).ToString()
If rd.HasRows Then
If rd.GetValue(11).ToString() = 1 Then
rd.Read()
lblinfo.Text = "You are Authorized."
FormsAuthentication.RedirectFromLoginPage(username.Text, True)
Response.Redirect("securepages/SecurePage.aspx")
Else
lblprompt.Text = "Invalid username or password."
End If
If rd.GetValue(11).ToString() = 2 Then
rd.Read()
FormsAuthentication.RedirectFromLoginPage(username.Text, True)
Response.Redirect("securepages/newShipment.aspx")
Else
lblprompt.Text = "Invalid username or password."
End If
End If
End While
Catch ex As Exception
lblprompt.Text = "Invalid username or password."
End Try
Could I get some help as to what am failing to do here?
At the very least, please write a basic POCO object to encapsulate the values from the data layer.
Use your datareader to POPULATE the Poco object, and insert some basic logic on the Poco object.
Use the datareader quickly, then get rid of it.
Then you could actually reuse the object and your logic.
Something like this.
Then (in the presentation layer) ~respond to the values in the Poco with the redirects and such.
public enum RedirectTypeEnum
{
Unknown = 0,
SecurePage = 1,
NewShipment = 2,
}
public class LoginAttemptResult
{
public LoginAttemptResult()
{
this.NumRecord = 0;
this.ResultNumberAkaColumn11 = 0;
}
public int NumRecord { get; set; }
public int ResultNumberAkaColumn11 { get; set; }
public RedirectTypeEnum RedirectType
{
get
{
RedirectTypeEnum returnValue = RedirectTypeEnum.Unknown;
if (this.ResultNumberAkaColumn11 == 1)
{
returnValue = RedirectTypeEnum.SecurePage;
}
if (this.ResultNumberAkaColumn11 == 2)
{
returnValue = RedirectTypeEnum.NewShipment;
}
return returnValue;
}
}
public bool IsAuthorized
{
get
{
if (this.ResultNumberAkaColumn11 == 1)
{
return true;
}
if (this.ResultNumberAkaColumn11 == 2)
{
return false; /* ?? */
}
return false;
}
}
}
Then you'll have one place where you populate this object, and someone can see clearly what the biz logic is by looking at the POCO object.
One issue that I see is that you are response.redirect'ing in a Try...Catch block. Unless you put , False (which allows the code to finish executing instead of aborting) after the URL, you will throw a Thread is aborting error every time it attempts to redirect.
As for the message not showing, you show how lblinfo is created, but what about lblprompt? Perhaps you have its visible property set to false? If this is the case, make sure to change it to true in the code. Also, make sure you are not clearing its value on events such as page_load.
I have also cleaned up the code a little bit and implemented a datatable object instead of the reader:
Try
Dim cmd As New SqlCommand("Check_Users", New SqlConnection(GetConnectionString()))
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New SqlParameter("Login_name", username.Text))
cmd.Parameters.Add(New SqlParameter("Login_Pwd", password.Text))
Dim sqlDataAdapter As New SqlClient.SqlDataAdapter(cmd)
Dim dtResults As New DataTable
sqlDataAdapter.Fill(dtResults)
lblprompt.Text = "Invalid username or password."
'check the Role of the user logging in'
If dtResults.Rows.Count > 0 Then
With dtResults.Rows(0)
Session("numrecord") = .Item(0).ToString()
If .Item(11).ToString() = 1 Then
lblprompt.Text = ""
FormsAuthentication.RedirectFromLoginPage(username.Text, True)
Response.Redirect("securepages/SecurePage.aspx", False)
ElseIf .Item(11).ToString() = 2 Then
lblprompt.Text = ""
FormsAuthentication.RedirectFromLoginPage(username.Text, True)
Response.Redirect("securepages/newShipment.aspx", False)
End If
End With
End If
Catch ex As Exception
lblprompt.Text = "An error has occurred." & ex.Message
End Try

Getting Email address from Active Directory

All --
I am able to retieve the FullName value
I am trying to retrieve an email address from Active Directory but using the following code in my ASP.Net Web Forms project that is using Windows Authentication:
Dim wi As System.Security.Principal.WindowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent()
Dim a As String() = wi.Name.Split(New Char() {"\"c}) '' Context.User.Identity.Name.Split('\')
Dim ADEntry As System.DirectoryServices.DirectoryEntry = New System.DirectoryServices.DirectoryEntry(Convert.ToString("WinNT://" + a(0) + "/" + a(1)))
Dim Name As String = ADEntry.Properties("FullName").Value.ToString()
Dim Email As String = ADEntry.Properties("mail").Value.ToString()
when I get to the line of code where I'm try to retrieve the email address I get an "Object reference not set to an instance of an object." error. I have tried using EmailAddress, E-Mail. I think the problem is that I am simply using the wrong keyword. I am able to retrieve the FullName value.
Thanks to Davide Piras who send me this link, I found a suitable solution:
Dim wi As System.Security.Principal.WindowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent()
Dim a As String() = wi.Name.Split(New Char() {"\"c}) '' Context.User.Identity.Name.Split('\')
Dim dc As PrincipalContext = New PrincipalContext(ContextType.Domain, "DomainName")
Dim adUser As UserPrincipal = UserPrincipal.FindByIdentity(dc, a(1))
Dim Email As String = adUser.EmailAddress
This code works for me..
Reference to System.DirectoryServices.AccountManagement
static string GetADUserEmailAddress(string username)
{
using (var pctx = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal up = UserPrincipal.FindByIdentity(pctx, username))
{
return up != null && !String.IsNullOrEmpty(up.EmailAddress) ? up.EmailAddress : string.Empty;
}
}
}
to use it:
lblEmail.Text = GetADUserEmailAddress(Request.ServerVariables["AUTH_USER"]);

LDAP Authentication The specified domain either does not exist or could not be contacted

I got the following error
{"The specified domain either does not exist or could not be
contacted. "}
at the line
Dim adResults = adSearch.FindOne.Path
Can anyone suggest why it is ? Seeing the below code
Dim ID As FormsIdentity = DirectCast(User.Identity, FormsIdentity)
Dim ticket As FormsAuthenticationTicket = ID.Ticket
Dim adTicketID As String = ticket.Name
Dim adSearch As New DirectorySearcher
adSearch.Filter = ("(userPrincipalName=" & adTicketID & ")")
Dim adResults = adSearch.FindOne.Path
Dim adResultsDirectory As New DirectoryEntry(adResults)
Dim found As Boolean = False
For Each entry In adResultsDirectory.Properties("memberOf")
Response.Write(entry)
Response.Write("<br/>")
If entry = "CN=GroupName,CN=UserGroup,DC=my,DC=domain,DC=com" Then
found = True
End If
Next
If Not (found) Then
Response.Redirect("login.aspx")
End If
Where is your domain specified?
First parameter for DirectoryEntry should be your AD server, something like this: LDAP://adserver.
Here is the code that I am using for checking whether user is authenticated in AD:
Dim dsDirectoryEntry As New DirectoryEntry("LDAP://" & domain, userName, password)
Dim dsSearch As New DirectorySearcher(dsDirectoryEntry)
Dim dsResults As SearchResult = dsSearch.FindOne()
If dsResults IsNot Nothing Then
Return True
Else
Return False
End If
Domain I am reading from configuration, userName and password are from login form input.

Resources