Why doesn't this code update the database table?

In a legacy ASP.NET Webforms application, I need to update the database table when the user clicks a button, depending on which checkboxes in the form are checked, using the value from the corresponding label to update.

This does not work; however, the nearly identical code in the "test" Winforms application does work.

FormLoad (Winforms) and Page_Load (Webforms) code works great; no need to show all this code; they both populate the form / page with label / checkbox control pairs.

To show how they differ from each other: if the controls are dynamically created, they assign a string value to the sign value (Winforms) or ID (Webforms) (more on that below).

In production (Winforms) code, this is done like this:

Dim lblCompanyName = New Label()
lblCompanyName.Tag = i.ToString()
lblCompanyName.Text = reader.Item(0).ToString()
Me.Controls.Add(lblCompanyName)

Dim ckbx = New CheckBox()
ckbx.Tag = i.ToString()
ckbx.Checked = True
Me.Controls.Add(ckbx)

      

In nonworking code (Webforms) it is done like this:

Dim coName = New Label()
' Must prepend with something, as controls cannot share the same ID
coName.ID = "lbl" + i.ToString()
coName.Text = categoryDT.Rows(i)(0).ToString()
formCustCatMaint.Controls.Add(coName)

Dim chk = New CheckBox()
chk.ID = "ckbx" + i.ToString()
chk.Checked = True
formCustCatMaint.Controls.Add(chk)

      

Besides the form / page load code, there are only three other blocks of code: a button click event handler and two utility methods called by this handler.

The code in a Winforms app that uses .NET Framework 4.5 works (updates the database table on button click); the code in a Webforms application that uses the .NET Framework 2 does not update the database table as it should - until it shows the err page, just smiles sweetly and lazily leans on its laurels.

The only real difference I can see in the code between the two is that in one case (Winforms app) a dynamically created control's tag property is assigned a value, while in the other (Webforms website) the dynamically created ID property of the control is it's appointed. By the way, neither technology has any other property available (Winforms cannot seem to access the ID property for the control, and Webforms cannot access the Tag property for the control).

A related difference is that no two controls can have the same ID (Webforms); so I need to add "lbl" to the Label control ids and "ckbx" to the Checkbox control ids (each pair shares the same number so that "lbl1" and "ckbx1" is a matching pair of "lbl42" and "lbl42" , ckbx42 "are a conjugate pair, etc.).

Why doesn't nearly identical code in a Webforms application update the database?

Here is the working (Winforms / .NET 4.5) code for these three blocks of code:

Private Sub Button1_Click( sender As Object,  e As EventArgs) Handles Button1.Click
        Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"
        Dim upd8DML As String = "UPDATE CustomerCategoryLog SET Category = 'Exploding' WHERE Unit = @Unit And MemberNo = @MemberNo AND Custno = @CustNo"

        Dim coName As String
        Dim argVals(2) As String
        Dim _Unit As String
        Dim _MemberNo As String
        Dim _CustNo As String
        Dim curTagVal As String

        For Each cntrl As Control In Me.Controls
                If TypeOf cntrl Is CheckBox Then
                    If DirectCast(cntrl, CheckBox).Checked = True Then
                        curTagVal = CStr(DirectCast(cntrl, CheckBox).Tag)
                        coName = GetLabelTextForTag(curTagVal)
                        argVals = GetArgValsForCompanyName(coName)
                        _Unit = argVals(0)
                        _MemberNo = argVals(1)
                        _CustNo = argVals(2)
                        Using conn As New SqlConnection(connStr), _
                            cmd As New SqlCommand(upd8DML, conn)
                            cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 50).Value = _Unit
                            cmd.Parameters.Add("@MemberNo", SqlDbType.VarChar, 50).Value = _MemberNo
                            cmd.Parameters.Add("@CustNo", SqlDbType.VarChar, 50).Value = _CustNo
                            conn.Open
                            cmd.ExecuteScalar()
                        End Using
                    End If
                End If
            Next
End Sub

    Protected Function GetLabelTextForTag(tagVal As String) As String
        Dim CoName As String = ""

        For Each cntrl As Control In Me.Controls
            If TypeOf cntrl Is Label Then
                If DirectCast(cntrl, Label).Tag.ToString() = tagVal Then
                    CoName = DirectCast(cntrl, Label).Text
                    Exit For
                End If
            End If
        Next
        Return CoName
    End Function

    Protected Function GetArgValsForCompanyName(coName As String) As String()
        Dim args(2) As String

        Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"),
              cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)

            con.Open()

            cmd.CommandType = CommandType.Text
            cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName

            Using reader As SqlDataReader = cmd.ExecuteReader

                While reader.Read
                    args(0) = reader.Item(0).ToString()
                    args(1) = reader.Item(1).ToString()
                    args(2) = reader.Item(2).ToString()
                End While

            End Using

        End Using

        Return args
    End Function

      

... and here is the non-working (Webforms / .NET 2.0) code for the relevant code points:

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"
    Dim upd8DML As String = "UPDATE CustomerCategoryLog SET Category = 'Exploding' WHERE Unit = @Unit And MemberNo = @MemberNo AND Custno = @CustNo"

    Dim coName As String
    Dim argVals(2) As String
    Dim _Unit As String
    Dim _MemberNo As String
    Dim _CustNo As String
    Dim curCheckboxIDVal As String

    For Each cntrl As Control In Me.Controls
            If TypeOf cntrl Is CheckBox Then
                If DirectCast(cntrl, CheckBox).Checked = True Then
                    curCheckboxIDVal = CStr(DirectCast(cntrl, CheckBox).ID)
                    coName = GetLabelTextForID(curCheckboxIDVal)
                    argVals = GetArgValsForCompanyName(coName)
                    _Unit = argVals(0)
                    _MemberNo = argVals(1)
                    _CustNo = argVals(2)
                    Using conn As New SqlConnection(connStr), _
                        cmd As New SqlCommand(upd8DML, conn)
                        cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 50).Value = _Unit
                        cmd.Parameters.Add("@MemberNo", SqlDbType.VarChar, 50).Value = _MemberNo
                        cmd.Parameters.Add("@CustNo", SqlDbType.VarChar, 50).Value = _CustNo
                        conn.Open
                        cmd.ExecuteScalar()
                    End Using
                End If
            End If
        Next
End Sub

Protected Function GetLabelTextForID(ckbxIDVal As String) As String
    Dim CoName As String = ""
    Dim _idVal As String = ckbxIDVal
    Dim numberLen As Integer = _idVal.Length - "ckbx".Length
    _idVal = _idVal.Substring("ckbx".Length, numberLen)
    LabelDebug.Text = _idVal

    For Each cntrl As Control In Me.Controls
        If TypeOf cntrl Is Label Then
            If DirectCast(cntrl, Label).ID = "lbl" + _idVal Then
                CoName = DirectCast(cntrl, Label).Text
                Exit For
            End If
        End If
    Next
    Return CoName
End Function

Protected Function GetArgValsForCompanyName(coName As String) As String()
    Dim args(2) As String

    Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"), _
          cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)

        con.Open()

        cmd.CommandType = CommandType.Text
        cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName

        Using reader As SqlDataReader = cmd.ExecuteReader

            While reader.Read
                args(0) = reader.Item(0).ToString()
                args(1) = reader.Item(1).ToString()
                args(2) = reader.Item(2).ToString()
            End While

        End Using
    End Using

    Return args
End Function

      

As you can see, the code is almost identical, but the results (success / failure) are diametrically opposed. Why?

UPDATE

Apparently this line doesn't work:

If TypeOf cntrl Is CheckBox Then

      

Although there are checkboxes on the page, this test fails. Why?

I know this because I added some "debug" tests inside the Button1_Click handler (can't go through the code):

For Each cntrl As Control In Me.Controls
    Label2.Text="label 2 text from foreach"
    If TypeOf cntrl Is CheckBox Then
        Label2.Text="label 2 text from is checkbox"
        If DirectCast(cntrl, CheckBox).Checked = True Then
            Label2.Text="label 2 text from checked"
            . . .

      

The last text written in Label2 is "label 2 text from foreach".

So, "If TypeOf cntrl is CheckBox Then" fails.

Are checkboxes not showing because they were created dynamically? If so, how can I get around this?

UPDATE 2

When I add this to the corresponding .aspx file:

<%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb" 
Inherits="pages_custmaint_categoryadmin" %>

      

(added "IsPostback =" true "part)

... "IsPostback" is underlined in red squigglies and when I run it I get:

Parser Error 
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. 

Parser Error Message: Error parsing attribute 'ispostback': The 'ispostback' property is read-only and cannot be set.

Source Error: 

Line 1:  <%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb" Inherits="pages_custmaint_categoryadmin" %>
Line 2:  
Line 3:  <!DOCTYPE html>

      

UPDATE 3

Now here's something super weird, it seems to me: I unchecked the checkbox in the Webform and ran it again. Even with the visible-at-design-time flag on the form, STILL doesn't pass the test "If TypeOf cntrl Is CheckBox Then"; last update for Label2.Text is still "label 2 text from foreach"

How can it be that a checkbox, especially a "specific" one and not a dynamic one, is not equal to a checkbox?!?

0


source to share





All Articles