We have the following code to check if the given username and password exists in database:
public User GetUserByUserNameAndPassword(string userName, string userPassword)
{
using (var context = DataObjectFactory.CreateContext())
{
return Mapper.Map(context.UserEntities.Single(u => u.UserName == userName && u.UserPassword == userPassword));
}
}
If we have the username and password in database this works fine but throws an error if username or password is wrong and no records found.
This might be simple but as I am new to lambda could not get get it right.
How can I change the lambda query so we can handle nulls?
Thanks
Use SingleOrDefault, which will return only one record or null if none exists.
return Mapper.Map(context.UserEntities.SingleOrDefault(u => u.UserName == userName && u.UserPassword == userPassword));
Later you can check:
User returnedObject = GetUserByUserNameAndPassword(username,password)
if(returnedObject == null)
{
//User doesn't exist
}
Remember Single/SingleOrDefault will throw an exception if multiple records exist against the criteria.
You should change from Single to SingleOrDefault, it returns null when no data match
context.UserEntities.SingleOrDefault(u => u.UserName == userName &&
u.UserPassword == userPassword)
.Any() will return true if a matching record is found or false if no record is found.
So a slight modifcation to you existing code will work.
public User GetUserByUserNameAndPassword(string userName, string userPassword)
{
using (var context = DataObjectFactory.CreateContext())
{
if (context.UserEntities.Any(u => u.UserName == userName && u.UserPassword == userPassword))
{
return Mapper.Map(context.UserEntities.Single(u => u.UserName == userName && u.UserPassword == userPassword));
}
else
{
//Deal with no user here through chosen method
}
}
}
Make use of FirstOrDefault or SingleOrDefualt and check for null like as below
var user =context.UserEntities.SingleOrDefault(u => u.UserName == userName
&&
u.UserPassword == userPassword);
if(user!=null)
{
//do code
}
Use SingleOrDefault and check for Null prior to calling Map
public User GetUserByUserNameAndPassword(string userName, string userPassword)
{
using (var context = DataObjectFactory.CreateContext())
{
var user = context.UserEntities.SingleOrDefault(u => u.UserName == userName && u.UserPassword == userPassword);
return user !=null ? Mapper.Map(user) : null;
}
}
Related
I'm trying to write this code for my project but it doesn't seem to work.
As you can see from the code, the last else statement won't work. I have a class Admin and it has 3 properties, Username, Password, and Permitted. I created a List with default values and granted some usernames permission while granting some no permission. From the else statement, I'm trying to match if the Permitted value is true then that user has permission, and vice versa, however even if the user has no permission is still grants him access. Any idea why?
List<Admin> result = FrmMain.AdminL.FindAll(adm => adm.UserName == txtUsername.Text);
if (result.Count == 0)
{
MessageBox.Show("Username is incorrect");
}
// Note to miss : I couldnt find a way to link the password with a specific user
List<Admin> result2 = FrmMain.AdminL.FindAll(adm => adm.PassWord == txtPassword.Text);
if (result2.Count == 0)
{
MessageBox.Show("Password is incorrect");
}
else
{
List<Admin> permission = FrmMain.AdminL.FindAll(adm => adm.Permitted == true);
if (result.Count > 0)
{
MessageBox.Show("User has been authenticated");
FrmAdminCP f1 = new FrmAdminCP();
f1.ShowDialog();
}
else
{
MessageBox.Show("Im sorry, you do not have permission to access the control panel");
}
You need to combine your predicates into a single search using &&.
List<Admin> result = FrmMain.AdminL.FindAll(adm =>
adm.UserName == txtUsername.Text &&
adm.PassWord == txtPassword.Text &&
adm.Permitted == true);
if (result2.Count == 1)
{
// authenticated with access
}
or two steps
List<Admin> result = FrmMain.AdminL.FindAll(adm =>
adm.UserName == txtUsername.Text &&
adm.PassWord == txtPassword.Text);
if (result.Count == 1)
{
// authenticated
}
else
{
// not authenticated
}
List<Admin> result = FrmMain.AdminL.FindAll(adm =>
adm.UserName == txtUsername.Text &&
adm.Permitted == true);
if (result.Count == 1)
{
// username is permitted to access
}
Update:
I'm assuming FrmMain.AdminL is a List<Admin>.
Admin singleResult = FrmMain.AdminL.Find(adm =>
adm.UserName == txtUsername.Text);
if(singleResult == null)
{
MsgBox("No User found");
return; // exit the subroutine you're in
}
if(singleResult.PassWord != txtPassword.Text)
{
MsgBox("Wrong Password");
return; // exit the subroutine you're in
}
if(singleResult.Permitted == false)
{
MsgBox("Not authorized")
return;
}
I want to query one more property of the "User" entity.
Basically I need to know, is it possible to extend the below statement to include something like this..
user = session.Query<User>().SingleOrDefault(u => u.Username.ToLower() == identity.ToLower()) && (u => u.Email == email);
I know thats not correct but you get the idea, I want to check the user email as well as the username.
This is the current code..
public static bool IsDuplicateIdentity(string identity, string email, Type type)
{
using(ISession session = NHibernateHelper.SessionFactory().OpenSession())
using (ITransaction tx = session.BeginTransaction())
{
User user = null;
// the entity type is checked and then DB is queried to see if an object with that name and email exists
if (type.BaseType == typeof(User))
{
user = session.Query<User>().SingleOrDefault(u => u.Username.ToLower() == identity.ToLower());
}
tx.Commit();
if (user != null)
{
return true;
}
else
{
return false;
}
}
}
Please note this is an ASP.net MVC 3 application.
Can't you just do this?:
user = session.Query<User>()
.SingleOrDefault(u =>
u.Username.ToLower() == identity.ToLower()
&& u.Email == email);
Sure:
user = session.Query<User>()
.SingleOrDefault(u => u.Username.ToLower() == identity.ToLower()
&& u.Email == email);
Yes, you can combine them and you almost got it right. Try it like this:
user = session.Query<User>().SingleOrDefault(u => u.Username.ToLower() == identity.ToLower() && u.Email == email);
You can write the below code
user = session.Query<User>()
.where(u => u.Username.ToLower() == identity.ToLower() && u.Email == email).SingleOrDefault();
I am trying to call the following get method in web api but I am currently experiencing an compiling error - 'bool' does not contain a definition for 'password' and no extension method 'password' accepting a first argument of type 'bool' could be found (are you missing a using directive or an assembly reference?) -- error
User class:
public class User : iUser
{
private cdwEntities db;
public User()
{
db = new cdwEntities();
}
public User(cdwEntities context)
{
db = context;
}
public bool Validate(string username, string password)
{
var query = from t in db.Trial_Try
join u in db.UserDetails on t.tUID equals u.uID
where t.tExpiryDate >= DateTime.Now &&
t.tPublication.Value == 163 &&
u.uUsername == username &&
u.uPassword == password
select u; //
// "execute" the query
return query.FirstOrDefault() != null;
}
Test class:
public HttpResponseMessage GetValidate(string username, string password)
{
User layer = new User();
var result = layer.Validate(username, password);
***if (result.username != null && result.password != null)***
{
var mes = string.Format("Success");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, mes);
}
else
{
//var mis = string.Format("User {0} not found");
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, mis, result);
return null;
}
}
Validate is returning a Boolean, not the result of the query. As #ekad stated, check result as a Boolean directly.
As an additional optimization, consider using .Any instead of FirstOrDefault since you don't need the hydrated result and can optimize the SQL to an Exists query rather than select top 1. Your validate method could then be:
public bool Validate(string username, string password)
{
var query = from t in db.Trial_Try
join u in db.UserDetails on t.tUID equals u.uID
where t.tExpiryDate >= DateTime.Now &&
t.tPublication.Value == 163 &&
u.uUsername == username &&
u.uPassword == password
select u; //
// "execute" the query
return query.Any();
}
The problem is result is a bool and it doesn't have username or password property, so you need to replace this line
if (result.username != null && result.password != null)
with this
if (result)
How do I get the Id in the login?
I'm using entity framework and in the frmLogin I have this:
private bool IsValidUser(string userName, string pass)
{
Context context = new Context();
var query = (from c in context.Cuentas
where c.Nombre == userName && c.Password == pass
select c);
return query.Any();
}
but with this function, I can only verify if the user is in the Database.
I want to get the id of this user too.
instead of the if(query.Any()) .... try:
var user = query.FirstOrDefault();
if (user == null)
return false;
var id = user.ID;
I think is possible to have only one user with th same username :) => one username = one user
you can try this
var user = context.Cuentas.singleordefault(d=>d.userName==userName & d.password==password);
int id;
if (user!=null)
{
id=user.userId;
return true;
}
return false;
EDITED
I am trying to find a user in my database, searching for email and phonenumber.
How ever, if I use a List or IEnumerable I'm getting a null refence exception. If I don't use any of those, an "Not supported by SQL ... " is thrown.
My method:
public List<tblMember> getAllMembers()
{
return db.tblMembers.ToList();
}
private void confirmMembership(string email, int phoneNumber)
{
//var allMembers = db.tblMembers.AsEnumerable(); throws same exception
tblMember member = getAllMembers().FirstOrDefault(x => x.email.Equals(email, StringComparison.OrdinalIgnoreCase) && x.phoneNumber == phoneNumber); //This line throws exception, around email.Equals()
if (member != null)
{
member.isConfirmed = true;
db.SubmitChanges();
}
else
throw new Exception("Member not found");
}
If I perform the search like this, no exception is thrown:
private void confirmMembership(string email, int phoneNumber)
{
//var allMembers = db.tblMembers.AsEnumerable(); throws same exception
tblMember member = getAllMembers().FirstOrDefault(x => x.email == email && x.phoneNumber == phoneNumber);
if (member != null)
{
member.isConfirmed = true;
db.SubmitChanges();
}
else
throw new Exception("Member not found");
}
How can this be?
In the first case you are calling Equals() on an object that is null.
x.email.Equals(...)
This throws an exception.
In the second case you are comparing two things one of which might be null
x.email == email
Here is the most current based on comments:
private void confirmMembership(string email, int phoneNumber)
{
tblMember member = tblMembers.FirstOrDefault((x) => {
if (x.email == null) return false;
return SqlMethods.Like(x.email,email) && x.phoneNumber == phoneNumber);
}
if (member != null)
{
member.isConfirmed = true;
db.SubmitChanges();
}
else
throw new Exception("Member not found");
}
Here is another way that won't throw an exception:
private void confirmMembership(string email, int phoneNumber)
{
//var allMembers = db.tblMembers.AsEnumerable(); throws same exception
tblMember member = getAllMembers().FirstOrDefault((x) => {
if (x.email == null) return false;
return x.email.Equals(email, StringComparison.OrdinalIgnoreCase) && x.phoneNumber == phoneNumber);
}
if (member != null)
{
member.isConfirmed = true;
db.SubmitChanges();
}
else
throw new Exception("Member not found");
}
This is probably because x.email is null. If it is null, calling a member of it throws an exception.
x.email.Equals(...) ==> exception
However, you are allowed to compare two values that may be null
x.email == email ==> OK.
I suspect it's because x.email is null for some value of x.
Try:
tblMember member = db.tblMembers
.FirstOrDefault(x => x.email != null
&& x.email.Equals(email, StringComparison.OrdinalIgnoreCase)
&& x.phoneNumber == phoneNumber);
EDIT: I've only just noticed that getAllMembers() returns a List<T> so you don't have to worry about the expression tree conversion I was talking about before - but your current code is fetching all the data from the database each time you call this method. Do you really want that? The code I've provided above will do the filtering in the database which is surely what you'd be interested in.