0

I have a LINQ statement handling the Login process. It works fine when passed valid username and password combinations. However when I test on invalid credentials, I get a NullReferenceException error on the line below indicated by <<<---------------- Need some help on proper handling of invalid credentials please?

public int _accountID;
public int _securityLevelID;
public void GetLoginInfo(string EmailAddress, string Password)
{
    LoginItem l = null;

    {
        try
        {
            using (RootsDataContext RDC = new RootsDataContext())

                l = (from a in RDC.DBLogIns
                     where a.EmailAddress == EmailAddress
                     && a.Password == Password
                     && a.IsActive == 1

                     select new LoginItem
                     {
                         AccountIDFK = a.AccountIDFK,
                         SecurityLevelIDFK = a.SecurtityLevelIDFK,

                     }).FirstOrDefault();

            _accountID = (int)l.AccountIDFK;      <<<---------------- 
            _securityLevelID = (int)l.SecurityLevelIDFK;

            if (_accountID < 1 || _accountID == null)
            {
                lbl_LoginStatus.Text = "Invalid";
            }

        }


        catch (Exception ex)
        {
            string error = ex.Message;
        }


        if (_accountID > 0)
        {
            if (_accountID == 1 && _securityLevelID == 1) // [Quentin]   
            {
                Response.Redirect("~/AccountsMaster.aspx");
            }

            if (_accountID > 1 && _securityLevelID == 2) // [Companies]    
            {
                Response.Redirect("~/CompanyMaster.aspx");
            }

            if (_accountID > 1 && _securityLevelID == 3) // [Branch]
            {
                Response.Redirect("~/BranchMaster.Aspx");
            }

            if (_accountID > 1 && _securityLevelID == 4) // [Clients]   
            {
                Response.Redirect("~/Home.aspx");
            }
        }
    }
}    
StuartLC
  • 104,537
  • 17
  • 209
  • 285
Quent
  • 79
  • 11

5 Answers5

2

By saying

  // ... 
  }).FirstOrDefault();

You will either get an DBLogIn object if a match is found, or null if it is not.

You will need to check for null before accessing the property AccountIDFK and SecurityLevelIDFK:

// ... }).FirstOrDefault();
if (l != null)
{
    _accountID = (int)l.AccountIDFK;
    _securityLevelID = (int)l.SecurityLevelIDFK;
}

Some other points to consider:

  • You shouldn't store passwords directly in the database. A more secure approach is to store hashed (and potentially salted) passwords in the database, and then to find the user (by EmailAddress and Active = 1), and then compare the hashes of what the user typed, and what is stored in the DB.
  • This code swallows exceptions - this makes diagnosing problems a nightmare:

    catch (Exception ex)
    {
        string error = ex.Message;
    }
    
  • Don't make fields public (public int _accountID;) - Make them private if they are not used externally, or convert them to (autogenerated) Properties if they are externally visible from your class.
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
1

FirstOrDefault method will return null if there's no DBLogIn records match the criteria you give, so you need to check if l is null first before accessing (int)l.AccountIDFK. Moreover, it looks like lbl_LoginStatus.Text = "Invalid"; should be done when l is null, so you need to remove if (_accountID < 1 || _accountID == null) block and change your code as follows:

if (l != null)
{
    _accountID = (int)l.AccountIDFK;
    _securityLevelID = (int)l.SecurityLevelIDFK;
}
else
{
    // logic when l is null
    lbl_LoginStatus.Text = "Invalid";
}

Alternatively you can also use C# Ternary Operator to check if l is null

_accountID = l != null ? (int)l.AccountIDFK : 0;
_securityLevelID = l != null ? (int)l.SecurityLevelIDFK : 0;

if (_accountID < 1)
{
    lbl_LoginStatus.Text = "Invalid";
}
ekad
  • 14,436
  • 26
  • 44
  • 46
0

You should check for null value in 'l' before using it.

if(l!=null)
{
_accountID = (int)l.AccountIDFK;    
            _securityLevelID = (int)l.SecurityLevelIDFK;
}
else
{
 lbl_LoginStatus.Text = "Invalid";
}
Pavan Teja
  • 3,192
  • 1
  • 15
  • 22
0

Linq FirstOrDefault returns null if there is no item in the list matching your query.So if you get null in your code means that user login is invalid.

 public int _accountID;
    public int _securityLevelID;
    public void GetLoginInfo(string EmailAddress, string Password)
    {
        LoginItem l = null;

        {
            try
            {
                using (RootsDataContext RDC = new RootsDataContext())

                    l = (from a in RDC.DBLogIns
                         where a.EmailAddress == EmailAddress
                         && a.Password == Password
                         && a.IsActive == 1

                         select new LoginItem
                         {
                             AccountIDFK = a.AccountIDFK,
                             SecurityLevelIDFK = a.SecurtityLevelIDFK,

                         }).FirstOrDefault();
              if(l==null || _accountID < 1 || _accountID == null)
              {
                 lbl_LoginStatus.Text = "Invalid";
                Response.Redirect("~/InvalidCredentials.aspx"); // redirect to invalid login page.
              }
              else
              {
               _accountID = (int)l.AccountIDFK;
                _securityLevelID = (int)l.SecurityLevelIDFK;

              }
            }


            catch (Exception ex)
            {
                string error = ex.Message;
            }


            if (_accountID > 0)
            {
                if (_accountID == 1 && _securityLevelID == 1) // [Quentin]   
                {
                    Response.Redirect("~/AccountsMaster.aspx");
                }

                if (_accountID > 1 && _securityLevelID == 2) // [Companies]    
                {
                    Response.Redirect("~/CompanyMaster.aspx");
                }

                if (_accountID > 1 && _securityLevelID == 3) // [Branch]
                {
                    Response.Redirect("~/BranchMaster.Aspx");
                }

                if (_accountID > 1 && _securityLevelID == 4) // [Clients]   
                {
                    Response.Redirect("~/Home.aspx");
                }

            }


        }

    }    
Konammagari
  • 364
  • 2
  • 8
0

You should have a check for LoginItem's default value null, and if its null (in case of invalid credentials) then do whatever you want.

Rohit
  • 1,520
  • 2
  • 17
  • 36