I want to check first if the user exists or not so I made a stored procedure in my SQL Server to check that.
CREATE PROCEDURE Login
#username varchar(20),
#password varchar(20),
#status int output
AS
IF EXISTS (SELECT username, password
FROM SystemUser
WHERE username = #username AND password = #password)
SET #status = 1
ELSE
SET #status = 0
Then, using ASP.NET Webforms, I'm creating a login page for the users
protected void login(object sender, EventArgs e)
{
String connstr = WebConfigurationManager.ConnectionStrings["Sports"].ToString();
SqlConnection conn = new SqlConnection(connstr);
String username = txt_Username.Text;
String password = txt_password.Text;
SqlCommand login = new SqlCommand("userLogin", conn);
login.CommandType = CommandType.StoredProcedure;
login.Parameters.Add(new SqlParameter("#username", username));
login.Parameters.Add(new SqlParameter("#password", password));
SqlParameter loginstatus = login.Parameters.Add("#status", SqlDbType.Int);
loginstatus.Direction = ParameterDirection.Output;
conn.Open();
login.ExecuteNonQuery();
conn.Close();
if (loginstatus.GetInt32 == 1)
{
Response.Write("hello");
Response.Redirect("Home.aspx");
}
}
However, I get an error:
Error CS1061 'SqlParameter' does not contain a definition for 'GetInt32' and no accessible extension method 'GetInt32' accepting a first argument of type 'SqlParameter' could be found (are you missing a using directive or an assembly reference?)
Any idea how can I compare the output from the stored procedure in the if condition?
Thanks in advance
I tried different types of methods like .value.
Expecting to know how to compare the value to an int.
you can get the value using .Value
if ((int)loginstatus.Value == 1)
{
...
}
There are other issues also in your code.
you are storing the password as plain text in a database table.
please use using with SqlConnection to dispose of automatically, same comment for SqlCommand .
and please use meaningful names when declaring variables like SqlCommand login. it's very unclear by the name login. it should be command or sqlCommand
Related
I want to catch on -1, 0, 1 values returning from the SQL Server stored procedure in C#.
SQL Server:
IF EXISTS(SELECT * FROM _Users WHERE UserName = #UserName AND [Password] != #Password)
BEGIN
RETURN -1
END
IF EXISTS(SELECT * FROM _Users WHERE UserName != #UserName AND [Password] != #Password)
BEGIN
RETURN 0
END
IF EXISTS(SELECT * FROM _Users WHERE UserName = #UserName AND [Password]= #Password)
BEGIN
RETURN 1
END
C#
Are we able to change the returning value of the code below just by making as I want to?
public User getUser(string name, string password)
{
User user = null;
using (var connection = Database.GetConnection())
{
var command = new SqlCommand("SP_GetUser #UserName, #Password", connection);
command.Parameters.Add(new SqlParameter("UserName", name));
command.Parameters.Add(new SqlParameter("Password", password));
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
user = new User();
user.UserId = Convert.ToInt32(reader["UserId"]);
user.userName = Convert.ToString(reader["UserName"]);
user.password = Convert.ToString(reader["Password"]);
}
}
connection.Close();
}
return user; // I want to return -1, 0, 1
}
SqlParameter returnValueParam = new SqlParameter() { Direction = ParameterDirection.ReturnValue };
command.Parameters.Add(returnValueParam);
// Read everything from your DataReader before trying to obtain the return value
// In fact after you close the connection
var returnValue = returnValueParam.Value;
Notes:
Ensure you set command.CommandType = CommandType.StoredProcedure; (and remove the parameters from the CommandText as it can only be the SP name when using CommandType.StoredProcedure).
You should always specify the datatype and scale/precision (if relevant) when creating a SqlParameter as there can be unexpected side effects allowing the datatype to be set automatically. Its also best practice to fully name the parameter, including the #, So
new SqlParameter("UserName", name);
should really be
// Where the type and length match your SP
new SqlParameter("#UserName", SqlDbType.NVarChar, 128) { Value = name };
Technically the return value of a stored procedure is for the "execution status" of the stored procedure. You would normally use an OUTPUT parameter to return user data. However in my opinion your use-case is as good as any.
As noted by #marc_s: you should not use the sp_ prefix for your stored procedures. Microsoft has reserved that prefix for its own use (see Naming Stored Procedures), and you do run the risk of a name clash sometime in the future. It's also bad for your stored procedure performance. It's best to just simply avoid sp_ and use something else as a prefix - or no prefix at all!
This question already has answers here:
SQL Case Sensitive String Compare
(6 answers)
Closed 5 years ago.
I'm new to coding in asp.net . I have done a (web form) login page and its validation in asp.net + c#. The problem is when i enter the password corresponding to the email in lower-case/upper-case letters, it grants me entry which is not supposed to happen. I have gone through a number of codes posted here for login page but the same thing is happening.
For eg,if the password in db is "ss"and if we type "ss","Ss", "sS" or "SS" ; i'm able to sign in. How can i stop this from happening?
I'm posting my code here. Please help.
protected void btn_login1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=SHA\SQLE2012;Initial Catalog=OnlineShoppingStore;User ID=sa;Password=56238");
con.Open();
SqlCommand cmd = new SqlCommand("usp_ViewUserByUserId", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Email", txt_email.Text);
cmd.Parameters.AddWithValue("#Password", txt_password.Text);
string output = cmd.ExecuteScalar().ToString();
cmd.ExecuteNonQuery();
if (output =="1")
{
Response.Write("<script>alert('Login Successful!!')</script>");
Session["Email"] = txt_email.Text;
Response.Redirect("Home.aspx");
}
else
Response.Write("<script>alert('Login Failed! Incorrect username/password')</script>");
con.Close();
}
This is my stored Procedure
ALTER PROCEDURE [dbo].[usp_ViewUserByUserId]
#Email as varchar(50),
#Password as varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select count(*) from tbl_Customer where Email = #Email and Password = #Password
end
Thank you all for taking the time to give suggestions.
The code below did the trick
select count(*)
from tbl_Customer
where Email = #Email and BINARY_CHECKSUM(Password) = BINARY_CHECKSUM(#Password)
I am trying to query services on a remote server and insert them into SQL. I know I am missing something that will actually write this back but I cannot figure out what it is. Everything works until I try to write the data to SQL.
static void Main(string[] args)
{
string username = ConfigurationManager.AppSettings["UserName"].ToString();
string password = ConfigurationManager.AppSettings["Password"].ToString();
string domain = ConfigurationManager.AppSettings["Domain"].ToString();
var logonType = SimpleImpersonation.LogonType.NewCredentials;
using (SimpleImpersonation.Impersonation.LogonUser(domain, username, password, logonType))
{
var connection = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connection))
{
conn.Open();
using (SqlCommand command = new SqlCommand("SELECT ServerName, ServerIP FROM Server", conn))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string serverIP = reader["ServerIP"].ToString();
string serverName = reader["ServerName"].ToString();
ServiceController[] services = ServiceController.GetServices(serverIP);
foreach (ServiceController service in services)
{
using (SqlCommand cmd = new SqlCommand("sp_InsertServices", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter ID = new SqlParameter();
ID.ParameterName = "#ID";
ID.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.AddWithValue("#ID", ID);
cmd.Parameters.AddWithValue("#Display", service.DisplayName);
cmd.Parameters.AddWithValue("#Service", service.ServiceName);
cmd.Parameters.AddWithValue("#Status", service.Status);
cmd.Parameters.AddWithValue("#Server", serverName);
}
}
}
}
}
}
}
Here is the Stored Proc
PROCEDURE [dbo].[sp_InsertServices]
#ID int,
#Display nvarchar(50),
#Service nvarchar(50),
#Status nvarchar(50),
#Server nvarchar(50)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Services
(ID,
DisplayName,
ServiceName,
Status,
Server)
VALUES
(#ID,
#Display,
#Service,
#Status,
#Server)
SET #ID = SCOPE_IDENTITY()
END
EDIT: Sorry some more info. I have added an execute at the end after the param adds and I get this error.
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Data.dll
Additional information: There is already an open DataReader associated with this Command which must be closed first.
Looks like I need to close the first reader but I still use it in the second command. Don't now where I can safely close it.
You never execute your SqlCommand. After you add your parameters, try adding cmd.ExecuteNonQuery();
The 2nd problem is that you are trying to reuse the same SqlConnection. You'll need to create a new SqlConnection since you are using your existing connection to loop through the list of servers.
You've built up the Command object (cmd), now you just need to save it, like cmd.ExecuteNonQuery();
First this you need to change the stored procedure declaration as
ALTER PROCEDURE [dbo].[sp_InsertServices]
#Display nvarchar(50),
#Service nvarchar(50),
#Status nvarchar(50),
#Server nvarchar(50)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Services
(DisplayName, ServiceName, Status, Server)
VALUES
(#Display,#Service,#Status,#Server)
SELECT SCOPE_IDENTITY()
END
And now change the calling code to
using (SqlCommand cmd = new SqlCommand("sp_InsertServices", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Display", service.DisplayName);
cmd.Parameters.AddWithValue("#Service", service.ServiceName);
cmd.Parameters.AddWithValue("#Status", service.Status);
cmd.Parameters.AddWithValue("#Server", serverName);
int serviceID = (int)cmd.ExecuteScalar();
// What you want to do with the ID returned?
}
The ID parameter is not needed if your ID field is an IDENTITY column, it is automatically calculated by the database and you could return it using a simple select. If your stored procedure ends with a SELECT SCOPE_IDENTITY() the result can be retrieved on the C# code using a simple ExecuteScalar without the need of an output parameter.
Finally, if you try to ExecuteXXX an SqlCommand using the same connection in use by a SqlDataReader you get an exception because the connection is busy serving the SqlDataReader and cannot execute the command.
The simple solution is to add this to your connection string
....;MultipleActiveResultSets=True;....
See MSDN for MultipleActiveResultSets
I am trying to execute a query with a condition like if username already present then update the row, else insert username and password.
This is my code below:
using (SqlCommand cmd = new SqlCommand("INSERT INTO Users(Username,Password) VALUES(#User,#password) ON DUPLICATE KEY UPDATE Username=VALUES(Username), Password=VALUES(Password)"))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#User", TextBox3.Text);
cmd.Parameters.AddWithValue("#password", Pwd);
con.Open();
cmd.ExecuteNonQuery();
}
I got the following error:
Incorrect syntax near the keyword 'ON'.
I am not able to figure out what is wrong in this. Can anyone please help me out?
In SQL Server you need to use a query something like this:
-- check if exists (by username) - if found, update password
IF EXISTS (SELECT * FROM dbo.Users WHERE Username = #User)
UPDATE dbo.Users
SET Password = #password
WHERE Username = #User
ELSE
INSERT INTO dbo.Users(Username, Password)
VALUES(#User, #password)
And as mentioned in my comments - do not use the .AddWithValue function (see linked blog post for details) but use this instead:
cmd.Parameters.Add("#User", SqlDbType.VarChar, 100).Value = TextBox3.Text;
And also, please do not store your passwords in clear text in the database!
It looks like you're using MySQL syntax. I don't think SQL Server has ON DUPLICATE KEY. You'd probably want a MERGE statement.
#marc_s
String query = #"IF EXISTS (SELECT * FROM Users WHERE Username = # User)
UPDATE Users
SET Password = #password
WHERE Username = # User
ELSE
INSERT INTO Users(Username, Password)
VALUES(# User, #password)";
using (SqlCommand cmd = new SqlCommand(query))
I used the code you gave and used to debug points to check if the code is executing ,and it was, still it is not updating or Inserting the values .I cant run the query in SQL server cause each time i open the query window VSudio restarts,i am using trial version of Visual Studio
I have this stored procedure for validating login
ALTER PROCEDURE ValidateUserLogin
(
#UserName varchar (50),
#Password varchar (50)
)
AS
BEGIN
if EXISTS(SELECT * FROM AdminLogin WHERE UserName=#UserName AND Password=#Password)
select 0/*returns 0 on success*/
ELSE
select 1/*non zero otherwise*/
END
and i am calling it using the code below but i get the following exception "Procedure or Function 'ValidateUserLogin' expects parameter '#UserName', which was not supplied."
bool boolReturnValue = true;
SqlCommand command = new SqlCommand();
command.Connection = sqlConnection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "ValidateUserLogin";
command.Parameters.Add(#username,SqlDbType.VarChar,50).Value=username;
command.Parameters.Add(#password, SqlDbType.VarChar,50).Value=password;
sqlConnection.Open();
try
{
command.ExecuteScalar();
boolReturnValue=Convert.ToBoolean( command.ExecuteScalar());
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
and when i try to set default value for the username and password as null i get the exception
#admin is not a parameter for procedure ValidateUserLogin
//admin is the value provided for username
Change the following two lines:
command.Parameters.Add(#username,SqlDbType.VarChar,50).Value=username;
command.Parameters.Add(#password, SqlDbType.VarChar,50).Value=password;
with:
command.Parameters.Add("#Username",SqlDbType.VarChar,50).Value=username;
command.Parameters.Add("#Password", SqlDbType.VarChar,50).Value=password;
You need to put your parameter name in quotes for the Add method. In other words, "#username" with the quotes.
If your database is case sensitive than the parameters have case sensitivity
command.Parameters.Add(#username,SqlDbType.VarChar,50).Value=username;
should have #UserName parameter to match the procedure's case.
Same applies for password of course.