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?!?
source to share
No one has answered this question yet
See similar questions:
or similar: