Looping Through RadioButtonLists

At the moment I am working on a Survey that contains tonnes of RadioButtonList controls that users will use to respond to the numerous questions I have on the website. All was going well until I thought about how I would find a quick and efficient way to enter all the RadioButtonList entries into my SQL database without having to do the following:

_rblBLL.InsertResults(1, rblist1.SelectedValue);
_rblBLL.InsertResults(2, rblist2.SelectedValue);
_rblBLL.InsertResults(3, rblist3.SelectedValue);
...
...
...
...

(InserResults() is my BLL function)

As you can see above, this is indeed a long winded way of inserting all my RadioButtonList entries to the database.

But I found a better way by using the FindControl() method:

for (int i=1; i < questionNo; i++)
{      
    RadioButtonList rbl = (RadioButtonList)this.FindControl("rblist" + i);

    if(rbl != null)
    {
         _rblBLL.InsertResults(i, rbl.SelectedValue);
    }
} 

As you can see, I created a for loop that will iterate through all the RadioButtonLists by incrementing the end value of RadioButtonList ID. So you will have to adopt a naming convention that has a number at the end as shown I have used above.

ASP.NET Login Authentication Problem

I was trying to create a Login page for my website in ASP.NET a couple of days ago and I was stumped that the following piece of code did not work:

private bool SiteLevelCustomAuthenticationMethod(string User, string Password)
{   
   bool boolReturnValue = false;
   DataTable dtAuthUsers = SomeBLL.GetUsers();
   if (dtAuthUsers != null && dtAuthUsers.Rows.Count > 0)
   {
       DataView dvAuthUsers = dtAuthUsers.DefaultView;
       foreach (DataRowView drvAuthUsers in dvAuthUsers)
       {
            if (User == drvAuthUsers.Row["User"].ToString() && Password == drvAuthUsers.Row["Password"].ToString())
            {
                boolReturnValue = true;
            }
        }
    }
    return boolReturnValue;
}

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
    bool Authenticated = false;
    Authenticated = SiteLevelCustomAuthenticationMethod(LoginControl.UserName, LoginControl.Password);
    e.Authenticated = Authenticated;
    if (Authenticated == true)
    {
        FormsAuthentication.RedirectFromLoginPage(string.Format("{0}", LoginControl.UserName), false);
    }
} 

Now after numerous debug sessions on this code, I could not find a thing wrong with it. The correct Username and Password was getting parsed to the Database but still the 'SiteLevelCustomAuthenticationMethod' function was still returning a false.

What was causing this problem was actually quite simple (even though it had taken my a long time to solve!). Basically, in the User's table in my database had the following columns:

  1. User_ID ------> DataType: int
  2. Username ------> DataType: nvarchar
  3. Password ------> DataType: char

Now this table look alright doesn't it? Well it isn't. The problem lies within the 'Password' column. Since this column format is 'char' with a length of 25, when you enter a password that is less than 25 characters in length a space will be added after to fill out the data length. For example, if you had a password that was 10 characters long, an extra 15 characters of spacing will be added after your password.

In order to fix this problem, I changed the Password DataType to 'nvarchar', which solved the problem.

Implement SCOPE_IDENTITY() in Data Access Layer

The SCOPE_IDENTITY() function are used in Insert queries to return the last identity value within your table. However, I never knew how to retrieve the ID value when using this function in my code.

Create an Insert Query in your Data Access Layer called "InsertUser". For example:

INSERT INTO Users (FirstName, LastName, DateOfBirth, Email, City) VALUES (@FirstName, @LastName, @DateOfBirth, @Email, @City);
SELECT SCOPE_IDENTITY() 

When you return to the DataSet Designer you'll see that the "InsertUser" method has been created. If this new method doesn't have a parameter for each column in the table, chances are you forgot to terminate the INSERT statement with a semi-colon. Configure the "InsertUser" method and ensure you have a semi-colon delimiting the INSERT and SELECT statements.

By default, insert methods issue non-query methods, meaning that they return the number of affected rows. However, we want the "InsertUser" method to return the value returned by the query, not the number of rows affected. To accomplish this, adjust the "InsertUser" method's ExecuteMode property to Scalar (this can be found in the Properties panel on the right).

The following code will put your new Insert Query into action:

int intUserID = Convert.ToInt32(BLL.InsertUser("John", "Doe", "16/06/1985", "joe@hotmail.com", "Oxford"));
//Output new User ID
Response.Write("New User ID Inserted: " + intUserID); 

For more info regarding the use of Data Access in ASP.NET 2.0 go to: http://msdn2.microsoft.com/en-us/library/Aa581778.aspx