Quent
Quent

Reputation: 79

Linq Select Statement help needed - NullReferenceException after using FirstOrDefault

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");
            }
        }
    }
}    

Upvotes: 0

Views: 116

Answers (5)

ekad
ekad

Reputation: 14614

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";
}

Upvotes: 1

StuartLC
StuartLC

Reputation: 107247

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.

Upvotes: 2

Rohit
Rohit

Reputation: 1550

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.

Upvotes: 0

Konammagari
Konammagari

Reputation: 364

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");
                }

            }


        }

    }    

Upvotes: 0

Pavan Teja
Pavan Teja

Reputation: 3202

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";
}

Upvotes: 0

Related Questions