Search code examples
c#htmldata-bindingknockout.jsrequest.form

Request.Form returning no values


I am working on an online registration form in HTML. Some of the fields are dynamically added using a foreach data-binding in knockout.js based on a collection of values. I have the jquery part complete so that it will add all of the text fields and collections.

The dynamic part of the form looks like this:

    <div class="form_section" ID="FamilyMembers" style="display:none;" >
        <div class="wFamilyMember" data-bind="foreach: $root.familyMembers" >
            <h2>Family Member <span data-bind="text: ($index() + 1)"></span> Information</h2>
            <div class='form_section'>
                <div class="eccform_column">
                    <div class="eccform_label">First Name*</div>
                    <div class="eccform_field"><input class="fmFirstName" title="First Name" type="text" data-bind="value:FirstName" /></div>
                </div>
                <div class="eccform_column">
                    <div class="eccform_label">Last Name *</div>
                    <div class="eccform_field"><input class="fmLastName" title="Last Name" data-bind="value:LastName"/></div>
                </div>
            </div>
            <div class="form_section">
                <div class="eccform_column">
                    <div class="eccform_label">Family Role*:</div>
                    <div class="eccform_dropdowns"><select class='fmFamilyRole' data-bind="options: $root.familyRoles, optionsText:'roleName', optionsValue:'value', value:FamilyRole"></select> </div>
                </div>
                <div class="eccform_column">
                    <div class="eccform_label">Age Group*:</div>
                    <div class="eccform_dropdowns"><select class='fmAgeGroup' data-bind="options:$root.ageGroups, optionsText:'groupName', optionsValue:'value', value:AgeGroup"></select></div>
                </div>
                <div class="eccform_checkbox_items">
                    <div class="eccform_checkbox"><input type="checkbox" class="fmLunchTicket" data-bind="checked: LunchTicket">Lunch Ticket ($5 for children, $10 for adults)</div>
                    <div class="eccform_checkbox"><input type="checkbox" class="fmSeminarTicket" data-bind="checked: SeminarTicket" >Seminar Ticket ($40)</div>
                </div>
            </div>
            <div class="form_section">
                <div class="eccform_column_button">
                    <button data-bind="click: $root.removeFamilyMember">Remove</button>
                </div>
            </div>
        </div>
        <button data-bind="click: $root.addFamilyMember">Add Family Member</button>
    </div>

    <div class="form_section" ID="Exhibitors" style="display:none;">
        <div class='wExhibitor' data-bind="foreach: $root.exhibitors">
            <h2>Exhibitor <span data-bind="text: $index() + 1"></span> Information</h2>
            <div class="eccform_section">
                <div class="eccform_column">
                    <div class="eccform_label">First Name*</div>
                    <div class="eccform_field"><input class="exFirstName" title="First Name" data-bind="value:FirstName" /></div>
                </div>
                <div class="eccform_column">
                    <div class="eccform_label">Last Name*:</div>
                    <div class="eccform_field"><input class="exLastName" title="Last Name" data-bind="value:LastName" /></div>
                </div>
            </div>
            <div class="eccform_section">
                <div class="eccform_column_exhibitor">
                    <div class="eccform_checkbox"><input type="checkbox" class="exLunchTicket" data-bind="checked: LunchTicket">Lunch Ticket ($10)</div>
                </div>
                <div class="eccform_column_exhibitor">
                    <div class="eccform_checkbox"><input type="checkbox" class="exSeminarTicket" data-bind="checked: SeminarTicket">Seminar Ticket ($40)</div>
                </div>
                <div class="eccform_column_removebutton">
                    <button data-bind="click: $root.removeExhibitor">Remove Exhibitor</button>
                </div>
            </div>
        </div>
        <button data-bind="click:$root.addExhibitor">Add Exhibitor</button>
    </div>

The problem is in that when I try to retrieve the values in C#, I don't seem to be able to read these dynamically added values. I use this code to read in the values:

                List<string> oFirstNames = ConvertFromEnumerable(Request.Form.AllKeys.Where(x => x.StartsWith("exFirstName")));
                List<string> oLastNames = ConvertFromEnumerable(Request.Form.AllKeys.Where(x => x.StartsWith("exLastName")));
                List<string> oLunchTickets = ConvertFromEnumerable(Request.Form.AllKeys.Where(x => x.StartsWith("exLunchTicket")));
                List<string> oSeminarTickets = ConvertFromEnumerable(Request.Form.AllKeys.Where(x => x.StartsWith("exSeminarTicket")));

This worked when I was using javascript to add new elements dynamically before, but it doesn't work now. It always returns a null or empty string set. I feel like I'm approaching this from the totally wrong angle, but I don't know what the right angle is. Should I be finding a way to get the data from the viewmodel instead? Any insights?


Solution

  • Alright, the solution was as simple as attaching the appropriate name onto the HTML DOM element. The final HTML ended up looking something like this:

        <div class="form_section" ID="Exhibitors" style="display:none;">
            <div class='wExhibitor' data-bind="foreach: $root.exhibitors">
                <h2>Exhibitor <span data-bind="text: $index() + 1"></span> Information</h2>
                <div class="eccform_section">
                    <div class="eccform_column">
                        <div class="eccform_label">First Name*</div>
                        <div class="eccform_field"><input id="exFirstName" runat="server" class="exFirstName" title="First Name" data-bind="value:FirstName,attr:{name: 'exFirstName_'+$index()}" /></div>
                    </div>
                    <div class="eccform_column">
                        <div class="eccform_label">Last Name*:</div>
                        <div class="eccform_field"><input id="exLastName" runat="server" class="exLastName" title="Last Name" data-bind="value:LastName, attr:{name: 'exLastName_'+$index()}" /></div>
                    </div>
                </div>
                <div class="eccform_section">
                    <div class="eccform_column_exhibitor">
                        <div class="eccform_checkbox"><input id="exLunchTicket" name="exLunchTicket" runat="server" type="checkbox" class="exLunchTicket" data-bind="checked: LunchTicket, attr: { name: 'exLunchTicket_' + $index() }">Lunch Ticket ($10)</div>
                    </div>
                    <div class="eccform_column_exhibitor">
                        <div class="eccform_checkbox"><input id="exSeminarTicket" name="exLunchTicket" runat="server" type="checkbox" class="exSeminarTicket" data-bind="checked: SeminarTicket, attr: { name: 'exSeminarTicket_' + $index() }">Seminar Ticket ($40)</div>
                    </div>
                    <div class="eccform_column_removebutton">
                        <button data-bind="click: $root.removeExhibitor">Remove Exhibitor</button>
                    </div>
                </div>
            </div>
            <button data-bind="click:$root.addExhibitor">Add Exhibitor</button>
        </div>
    

    Notice this section: attr: { name: 'exSeminarTicket_' + $index() }.

    Then, in the C# I corrected the code to look like this:

    int SomeKeys = Request.Form.AllKeys.Where(x=>x.StartsWith("exFirstName")).Count();
    
    for (int i = 0; i < SomeKeys; i++)
    {
        string FirstName = Request.Form["exFirstName_" + i];
        string LastName = Request.Form["exLastName_" + i];
        bool LunchTicket = Convert.ToBoolean(Request.Form["exLunchTicket_" + i]);
        bool SeminarTicket = Convert.ToBoolean(Request.Form["exSeminarTicket_" + i]);
    
        if (FirstName != "" && LastName != "")
            lFamilyMembers.Add(new FamilyMember(FirstName, LastName, SeminarTicket, LunchTicket, AgeGroup.Twenties, FamilyRole.Exhibitor));
    }