Search code examples
asp.netvb.nettextboxduplicate-datamodalpopup

Textbox in modal popup inserts duplicate entries


My textbox is supposed to enter one value and enters about 8 of the same thing. Anyone know why?

    <li class="item">
        <asp:LinkButton ID="FeatureButton" runat="server">Feature</asp:LinkButton>
        <asp:Panel ID="FeaturePanel" runat="server" CssClass="modalPopup" 
         Style="display:none">
            <div class="PopupHeader">Add a Feature</div>
            <asp:CheckBoxList ID="cbxAddFeature" runat="server" 
             DataSourceID="dsNewFeatures" DataTextField="FeatureTitle" 
             DataValueField="FeatureID"></asp:CheckBoxList>
            New Feature:<asp:TextBox ID="txtFeature" runat="server"></asp:TextBox>
            <asp:Label ID="FeatureError" runat="server" ></asp:Label>
            <asp:Button ID="SubmitFeatures" runat="server" Text="Submit" />
            <asp:Button ID="CancelSubmitFeatures" runat="server" Text="Cancel" />
        </asp:Panel>
        <asp:ModalPopupExtender ID="FeatureModal" runat="server" 
         BackgroundCssClass="modalBackground" 
         CancelControlID="CancelSubmitFeatures" DropShadow="True" 
         DynamicServicePath="" Enabled="True" PopupControlID="FeaturePanel" 
         TargetControlID="FeatureButton"></asp:ModalPopupExtender>
Protected Sub SubmitFeatures_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles SubmitFeatures.Click
    FeatureModal.Hide()
    For Each feature As ListItem In cbxAddFeature.Items
        If feature.Selected Then
            'SQL INSERT: Marketing Table
            Dim strSQL As String = "INSERT INTO Marketing (ProductID,
                                    MarketingTypeID, MarketingTitle, MarketingData) 
                                    VALUES (@ProductID, 3, 'Feature', @MarketingData);
                                    UPDATE Product SET ModifyDate = getdate(),
                                    ModifyUser = @ModifyUser 
                                    WHERE ProductID = @ProductID"

This is the code for the entire modal pop up, which includes an insert for checkboxes as well. If the user doesn't see an appropriate checkbox, they can enter a new value via textbox.

Protected Sub SubmitFeatures_Click(ByVal sender As Object, ByVal e 
As System.EventArgs) Handles SubmitFeatures.Click
    FeatureModal.Hide()
    For Each feature As ListItem In cbxAddFeature.Items
        If feature.Selected Then

            Dim strSQL As String = "INSERT INTO Marketing (ProductID,
                                    MarketingTypeID, MarketingTitle, MarketingData) 
                                    VALUES (@ProductID, 3, 'Feature', @MarketingData);
                                    UPDATE Product SET ModifyDate = getdate(),
                                    ModifyUser = @ModifyUser
                                    WHERE ProductID = @ProductID"

            Using cn As New SqlConnection
             (System.Configuration.ConfigurationManager.ConnectionStrings
             ("LocalSqlServer").ConnectionString)

                Using cmd As New SqlCommand(strSQL, cn)

                    cmd.Parameters.Add(New SqlParameter("@ProductID", 
                    ProductID.Value))
                    cmd.Parameters.Add(New 
                    SqlParameter("@MarketingData", feature.Value))
                    cmd.Parameters.Add(New SqlParameter("@ModifyUser",
                    System.Web.HttpContext.Current.User.Identity.Name))

                    cn.Open()

                    cmd.ExecuteNonQuery()
                End Using

                cn.Close()
            End Using
        Else
        End If
        If Not String.IsNullOrEmpty(txtFeature.Text) Then
            Dim featureSql As String = "INSERT INTO Feature (FeatureTitle)
                                        VALUES (@FeatureTitle);
                                        INSERT INTO Marketing(ProductID, 
                                        MarketingTypeID, MarketingTitle, MarketingData) 
                                        VALUES (@ProductID, 3, 'Feature', 
                                        scope_identity());
                                        UPDATE Product SET ModifyDate = getdate(), 
                                        ModifyUser = @ModifyUser 
                                        WHERE ProductID = @ProductID"

            Using cn As New SqlConnection
            (System.Configuration.ConfigurationManager.ConnectionStrings
            ("LocalSqlServer").ConnectionString)

                Using cmd As New SqlCommand(featureSql, cn)

                    cmd.Parameters.Add(New SqlParameter("@FeatureTitle",
                    txtFeature.Text))
                    cmd.Parameters.Add(New SqlParameter("@ProductID", 
                    ProductID.Value))
                    cmd.Parameters.Add(New SqlParameter("@ModifyUser", 
                    System.Web.HttpContext.Current.User.Identity.Name))

                    cn.Open()

                    cmd.ExecuteNonQuery()
                End Using

                cn.Close()
            End Using
        End If
    Next
    'keep tab active and redirect to same page
    Session("ActiveTabIdx") = TabContainer1.ActiveTabIndex
    Response.Redirect(Request.RawUrl)
End Sub

Solution

  • I think it's because of this:

    If feature.Selected Then
     ...   
    Else
      ....
    End If
    

    That means that for every item in the checkbox list it will always go into the Else block when the checkbox is not selected, which is causing multiple inserts.

    Extra suggestions

    Don't mix your UI code and your data access code on the same class/page. A good practice is to separate UI from Business Logic from Data Access logic. For example, this code:

    Dim strSQL As String = "INSERT INTO Marketing (ProductID,
                                        MarketingTypeID, MarketingTitle, MarketingData) 
                                        VALUES (@ProductID, 3, 'Feature', @MarketingData);
                                        UPDATE Product SET ModifyDate = getdate(),
                                        ModifyUser = @ModifyUser
                                        WHERE ProductID = @ProductID"
    
                Using cn As New SqlConnection
                 (System.Configuration.ConfigurationManager.ConnectionStrings
                 ("LocalSqlServer").ConnectionString)
    
                    Using cmd As New SqlCommand(strSQL, cn)
    
                        cmd.Parameters.Add(New SqlParameter("@ProductID", 
                        ProductID.Value))
                        cmd.Parameters.Add(New 
                        SqlParameter("@MarketingData", feature.Value))
                        cmd.Parameters.Add(New SqlParameter("@ModifyUser",
                        System.Web.HttpContext.Current.User.Identity.Name))
    
                        cn.Open()
    
                        cmd.ExecuteNonQuery()
                    End Using
    
                    cn.Close()
                End Using
    

    Can be moved entirely to another class that receives 3 parameters: UserID, ProductID and MarketingData. By doing this, you can reuse it on other places(pages, for example) instead of having to repeat the logic again and again.

    Optimally, you should have a business layer that calls your Data Access layer (Above code will go into your Data Access Layer) but at least moving this code to a different place is a good start. Another advantage besides being able to reuse your code is that supposing that you detect an error on this routine, you can fix it on one place as opposed to having to go to different places on your app to correct your error.