How do you handle the output of a dynamically generated form in ASP.NET MVC?

后端 未结 4 1682
失恋的感觉
失恋的感觉 2020-12-19 18:00

Say you create a form using ASP.NET MVC that has a dynamic number of form elements.

For instance, you need a checkbox for each product, and the number of products ch

相关标签:
4条回答
  • 2020-12-19 18:07

    Depending on the binders you are using, this should work:

    <%var i = 0;
      foreach (var product (IList<ProductSelection>)ViewData["products"]) {%>
          <%=Html.Hidden(string.Format("products[{0}].Id", i), product.Id)%>
          <%=Html.Checkbox(string.Format("products[{0}].Selected", i))%>
          <%=product.Name%><br/>
    <%}%>
    

    ...which will result in HTML something like this (notice the array notation on the names):

    <input name="products[0].Id" type="hidden" value="123">
    <input name="products[0].Selected" type="checkbox">
    Widget
    <input name="products[1].Id" type="hidden" value="987">
    <input name="products[1].Selected" type="checkbox">
    Gadget
    

    ...and the controller method that handles the post:

    public ActionResult SelectProducts(IList<ProductSelection> products)
    {
         ...
    }
    

    Upon binding, products parameter will contain two instances of ProductSelection.

    One caveat is that I have not used the new default binding for complex objects. Rather I am using either the NameValueDeserializer or CastleBind, both from MvcContrib. They both behave this way. I am guessing binding in the Beta will work the same way.

    0 讨论(0)
  • 2020-12-19 18:08

    Per Craig's answer.. that is safer. There are quirks to posting multiple form elements with the same name. I would add that it would be wise to wrap the logic that makes the "collection" of controls in a way similar to WebForms. Web Forms prepend the container control's name and adds an index. For example, in a Repeater the form elements inside would be named (something like) RepeaterName_Element1, RepeaterName_Element2. When you go to get the elements out, you have to use FindControl or something of the sort.

    0 讨论(0)
  • 2020-12-19 18:20

    Depending on your data, you could either output a 'CheckboxList' (which is not possible in the newer versions any more) and use a string[] parameter, or you could set up multiple forms and just modify the action.

    0 讨论(0)
  • 2020-12-19 18:25

    Just give each checkbox a unique name value:

    <input class="approveCheck" id="<%= "approveCheck" + recordId %>" 
     name="<%= "approveCheck" + recordId %>" type="checkbox" />
    

    Then parse the list of form values in the Action, after submit:

    foreach (var key in Request.Form.Keys)
        {
            string keyString = key.ToString();
            if (keyString.StartsWith("approveCheck", StringComparison.OrdinalIgnoreCase))
            {
                string recNum = keyString.Substring(12, keyString.Length - 12);
    
                string approvedKey = Request.Form["approveCheck" + recNum];
                bool approved = !String.IsNullOrEmpty(approvedKey);
                // ...
    

    You don't need to pass form values as arguments; you can just get them from Request.Form.

    One other option: write a model binder to change the list into a custom type for form submission.

    0 讨论(0)
提交回复
热议问题