i have an if statements align with a query in Linq to create the login in my app, but, the code works bad, when the query don't select any record, the .Count() it's equal to zero and it have sense, but in the if, the code never reach the else part, look, this is my code:
var UserLogin = from m in _context.User where m.Username.Contains(this.Username) & m.Password.Contains(this.Password) select m.Username;
this.Username = string.Empty;
this.Password = string.Empty;
if(UserLogin.Count() != 0)
{
//HttpContext.Session.SetString("Username", UserLogin.First());
UsernameLogged = UserLogin.First();
}
else
{
Console.WriteLine("Sisa: " + UsernameLogged);
this.Username = string.Empty;
this.Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
}
Note that the query is executed twice. The first time when you call UserLogin.Count(). The second time when you call UserLogin.First(). But then, you already have set Username and Password to string.Empty and all the user names and passwords do contain an empty string because String.Contains tests only whether a part of the string matches. So you are getting all the users in the result. Use == to test the whole string.
Since you want to get only one user, use FirstOrDefault which returns null when no user was found.
var userLogged = _context.User
.FirstOrDefault(u => u.Username == Username && u.Password == Password);
if (userLogged is null) {
Console.WriteLine("Sisa: " + UsernameLogged);
Username = string.Empty;
Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
} else {
UsernameLogged = userLogged.Username;
}
You are setting Username and Password to string.Empty twice. Either clear them after the if-else if you always want to do so, or do it only when no user was found.
This is because of you are using deferred execution of LINQ query. Your query is executed in if condition and there you will get count 1.
Use below code -
var UserLogin = from m in _context.User where m.Username.Contains(this.Username) & m.Password.Contains(this.Password) select m.Username;
var count = UserLogin.Count(); // Here your query will be execute
this.Username = string.Empty;
this.Password = string.Empty;
if(count != 0)
{
//HttpContext.Session.SetString("Username", UserLogin.First());
UsernameLogged = UserLogin.First();
}
else
{
Console.WriteLine("Sisa: " + UsernameLogged);
this.Username = string.Empty;
this.Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
}
This will execute your else condition.
Related
In my C# application I use 2 connection strings (application_cs, users_cs). To change these connection strings I use:
private static void SetProviderConnectionString(string connectionString)
{
var connectionStringFieldM =
Membership.Provider.GetType().GetField("_sqlConnectionString",
BindingFlags.Instance | BindingFlags.NonPublic);
var connectionStringFieldR = Roles.Provider.GetType().GetField("_sqlConnectionString",
BindingFlags.Instance | BindingFlags.NonPublic);
var connectionStringFieldP = ProfileManager.Provider.GetType().GetField("_sqlConnectionString",
BindingFlags.Instance | BindingFlags.NonPublic);
connectionStringFieldM.SetValue(Membership.Provider, connectionString);
connectionStringFieldR.SetValue(Roles.Provider, connectionString);
connectionStringFieldP.SetValue(ProfileManager.Provider, connectionString);
}
public static void SetProviderUsers()
{
SetProviderConnectionString(ConfigurationManager.ConnectionStrings["users_cs"].ConnectionString);
}
public static void SetProviderApp()
{
SetProviderConnectionString(ConfigurationManager.ConnectionStrings["application_cs"].ConnectionString);
}
So in my code whenever I want to add a user I do this:
public int CreateUser(int stid, int cid, int usrId, string email, string tel, string mob, string username,
bool create, bool prime)
{
int result = 0;
Guid userid = new Guid();
DALUsers.UserDBDataContext dc = new DALUsers.UserDBDataContext();
DAL.AppDataContext d = new DAL.AppDataContext();
BLL.Security.SetProviderUsers();
if (create) //create the user first
{
string question = "1";
string answer = "1";
bool isAproved = true;
string password = System.Web.Security.Membership.GeneratePassword(8, 2);
MembershipCreateStatus cs = new MembershipCreateStatus();
MembershipUser newUser = Membership.CreateUser(username, password, email, question, answer, isAproved, out cs);
Membership.UpdateUser(newUser);
Roles.AddUserToRole(username, "User_x");
if (cs == MembershipCreateStatus.Success)
{
result = 1;
}
else
X.MessageBox.Info("Error", "Cannot create user due to :" + cs.ToString(), UI.Danger).Show();
}
//at this point we have the user created either way.
// return userid;
var id = (from i in dc.aspnet_Users where i.UserName.CompareTo(username) == 0 select i.UserId);
if (id.Count() == 1)
{
userid = id.First();
bool contin = true;
var fulname = (from i in dc.Clients where i.id == usrId select i).First();
if (String.IsNullOrEmpty(fulname.Mobile)) fulname.Mobile = mob;
fulname.Email = email;
fulname.ModifiedBy = HttpContext.Current.User.Identity.Name;
fulname.ModifiedDate = DateTime.Now;
dc.SubmitChanges();
DateTime dt = DateTime.Now;
DALUsers.CIUser usr = new DALUsers.CIUser();
var existing = (from i in dc.CIUsers where i.UserName.CompareTo(username) == 0 && i.cid == cid select i);
if (existing.Count() > 0)
{
X.MessageBox.Info("Warning", "UserName already exists . Please try another!", UI.Warning).Show();
contin = false;
}
else
{
dc.CIUsers.InsertOnSubmit(usr);
dc.SubmitChanges();
}
if (contin)
{
DALUsers.CIUser usrNew = new DALUsers.CIUser();
var approved = (from k in dc.aspnet_Memberships //if user is not approved
where k.UserId == userid
select k).FirstOrDefault();
if (approved.IsApproved == false)
{
approved.IsApproved = true;
}
ProfileBase profile = ProfileBase.Create(username);
profile.SetPropertyValue("Mobile", mob);
profile.SetPropertyValue("Email", email);
profile.Save();
usrNew.UserId = usrId;
usrNew.cid = cid;
usrNew.FullName = fulname.LastName + " " + fulname.FirstName;
usrNew.Role = "User_x";
usrNew.SignRights = prime;
usrNew.IsPrime = prime;
usrNew.stid = stid;
usrNew.UserName = username;
usrNew.UserId = userid;
usrNew.CreatedDate = DateTime.Now;
usrNew.CreatedBy = HttpContext.Current.User.Identity.Name;
dc.CIUsers.InsertOnSubmit(usrNew);
dc.SubmitChanges();
result = 1;
X.MessageBox.Info("Success", "The user has been successfully added", UI.Success).Show();
}
}
else
X.MessageBox.Info("Error", "Could not find the user", UI.Danger).Show();
BLL.Security.SetProviderApp();
return result;
}
EDIT
I just saw that in my code there is this line:
DALUsers.aspnet_User user = new DALUsers.aspnet_User();
But the variable user is not used anywhere else in the code. Probably it has been left there... And its the only variable named user in my code. Is that causing the issue? But then why only on the production server?
EDIT
The weird part is that when I run my application from visual studio locally it works as a charm. But when I am adding a user in the application running on the production server when I am trying to add the second user it fails and I receive this error:
Value cannot be null. Parameter name: user
And if I try to login to my application after that it fails. I have to restart my website from iis to be able to login again.
Any ideas?
Well I cant find the error in your code but if you say that this error occurs only in server and that you are sure that your files are synched between server and your local machine, then probably the error lies in your web.config. Take a look
My code, upon compilation, throws the titular exception. I don't understand why this happens because after extensive searching the reason the error occurs is seemingly only when conditions exist where there is no exit return statement, and yet I think my code is fully inclusive.
bool CheckExisting()
{
Account loginAcc = new Account();
string path = Application.StartupPath.ToString() + "\\Customers";
int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
for(int i = 0;i<fCount;i++)
{
String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
XmlDocument xmlFile =new XmlDocument();
xmlFile.Load(filePaths[i]);
foreach(XmlNode node in xmlFile.SelectNodes("//Account"))
{
string firstName = node.SelectSingleNode("FirstName").InnerText;
string lastName = node.SelectSingleNode("LastName").InnerText;
string address1 = node.SelectSingleNode("Address1").InnerText;
string address2 = node.SelectSingleNode("Address2").InnerText;
string postCode = node.SelectSingleNode("Postcode").InnerText;
string telePhone = node.SelectSingleNode("Telephone").InnerText;
string mobile = node.SelectSingleNode("Mobile").InnerText;
Account newAcc = new Account();
newAcc.firstName = firstName;
newAcc.lastName = lastName;
newAcc.address1 = address1;
newAcc.address2 = address2;
newAcc.postCode = postCode;
newAcc.telephone = telePhone;
newAcc.mobile = mobile;
loginAcc = newAcc;
}
if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
{
return true;
}
else
{
return false;
}
return false;
}
}
Your code is effectively:
bool CheckExisting()
{
// Some setup code
for (int i = 0; i < fCount; i++)
{
// Code which isn't terribly relevant
return ...;
}
}
Now the C# 5 language specification section 8.8.3 talks about the reachability of the end of a for statement:
The end point of a for statement is reachable if at least one of the following is true:
The for statement contains a reachable break statement that exits the for statement.
The for statement is reachable and a for-condition is present and does not have the constant value true.
The latter is true in this case, so the end of the for statement is reachable... and that's the end of the method. The end of a method with a non-void return type can never be reachable.
Note that this is the case even if a human could detect that you can never reach the end of the for statement. For example:
bool Broken()
{
for (int i = 0; i < 5; i++)
{
return true;
}
// This is still reachable!
}
We know that the loop will always execute at least once, but the language rules don't - therefore the end of the statement is reachable, and you get a compile-time error.
If fCount were to be 0 then your loop would not execute and you'll not hit any of the return statements.
Some condensing and improved indentation makes it clear:
int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
for(int i = 0;i<fCount;i++){
...
if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName){
return true;
}
else{
return false;
}
return false;
}
Possibly in the "real world" fCount can never be 0, however compiler/runtime won't know this.
That happened because after for loop you have returned Nothing.
When your method executes it is expected to return the type you defined. When the code execution path goes into your for statement, it is fine because it returns. If the code does NOT go into the for loop, that your code does not return anything. That is the error. Run time exception likely .Walk through the code with pencil and paper and see how it executes
You missed a return. This should work.
bool CheckExisting()
{
Account loginAcc = new Account();
string path = Application.StartupPath.ToString() + "\\Customers";
int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
for(int i = 0;i<fCount;i++)
{
String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
XmlDocument xmlFile =new XmlDocument();
xmlFile.Load(filePaths[i]);
foreach(XmlNode node in xmlFile.SelectNodes("//Account"))
{
string firstName = node.SelectSingleNode("FirstName").InnerText;
string lastName = node.SelectSingleNode("LastName").InnerText;
string address1 = node.SelectSingleNode("Address1").InnerText;
string address2 = node.SelectSingleNode("Address2").InnerText;
string postCode = node.SelectSingleNode("Postcode").InnerText;
string telePhone = node.SelectSingleNode("Telephone").InnerText;
string mobile = node.SelectSingleNode("Mobile").InnerText;
Account newAcc = new Account();
newAcc.firstName = firstName;
newAcc.lastName = lastName;
newAcc.address1 = address1;
newAcc.address2 = address2;
newAcc.postCode = postCode;
newAcc.telephone = telePhone;
newAcc.mobile = mobile;
loginAcc = newAcc;
}
if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
{
return true;
}
else
{
return false;
}
return false;
}
return false;
}
bool CheckExisting(){
Account loginAcc = new Account();
string path = Application.StartupPath.ToString() + "\\Customers";
int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
for(int i = 0;i<fCount;i++){
String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
XmlDocument xmlFile =new XmlDocument();
xmlFile.Load(filePaths[i]);
foreach(XmlNode node in xmlFile.SelectNodes("//Account")){
string firstName = node.SelectSingleNode("FirstName").InnerText;
string lastName = node.SelectSingleNode("LastName").InnerText;
string address1 = node.SelectSingleNode("Address1").InnerText;
string address2 = node.SelectSingleNode("Address2").InnerText;
string postCode = node.SelectSingleNode("Postcode").InnerText;
string telePhone = node.SelectSingleNode("Telephone").InnerText;
string mobile = node.SelectSingleNode("Mobile").InnerText;
Account newAcc = new Account();
newAcc.firstName = firstName;
newAcc.lastName = lastName;
newAcc.address1 = address1;
newAcc.address2 = address2;
newAcc.postCode = postCode;
newAcc.telephone = telePhone;
newAcc.mobile = mobile;
loginAcc = newAcc;
}
if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName){
return true;
}
else{
return false;
}
return false;
}
??????
}
not returning anything if you are not entering into the for loop.
or you are not returning anything if your "FCount" is "0".
To put it simply, just add a default return false at the end. Here's your code snippet:
if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
{
return true;
}
else
{
return false;
}
return false;
}
return false;
}
Just think about the case scenario where fCount is zero or less than it.
for(int i = 0;i<fCount;i++)
The for loop will be skipped. So where's the return statement for that? That's why the compiler is throwing this error.
I think you meant to do this: (I'm stealing CodeCaster's cleaned up version)
bool CheckExisting()
{
//
for(/**/)
{
//
foreach(/**/)
{
//
}
if(/**/)
{
return true;
}
else
{
return false;
}
// return false; NOT HERE, because it's not reachable in the first place.
}
return false; // BUT HERE, in case fCount = 0
}
Also, you could do away with the if-else at the end and just do
return txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName;
... since that's a boolean expression already.
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
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;
}
}
How come my code is showing a syntax error on this block of code
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).First();
if (password == 0)
{ }
return password;
}
I want to know if the result of query is 0, if it is 0 I will close the operation or something like that. but It keeps showing an error how would I know if the result is 0? also if you have suggestions regarding my approach feel free to put it in
Calling .First() will result in an exception if there is no data returned...
Calling .FirstOrDefault() will return null if there is no data
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).FirstOrDefault();
if (password == null)
{
// no data found - do whatever is needed in that case...
}
return password;
}