10

I have a form which allows the user to create extra "rows" using JQuery (using .clone) so that they can decide how many of the same information they need to submit. My issue is that I cannot work out how to access these form items within my controller.

the form that is being submitted may look like this

<input type="text" name="Amount" id="Amount">
   <select name="Item">
       <option value="1">Item 1"</option>
       <option value="2">Item 2"</option>
       <option value="3">Item 3"</option>
   </select>
<input type="text" name="Amount" id="Amount">
   <select name="Item">
       <option value="1">Item 1"</option>
       <option value="2">Item 2"</option>
       <option value="3">Item 3"</option>
   </select>
<input type="text" name="Amount" id="Amount">
   <select name="Item">
       <option value="1">Item 1"</option>
       <option value="2">Item 2"</option>
       <option value="3">Item 3"</option>
   </select>

Basically, the block between input and the select could be repeated an infinite number of times. When I submit to the controller I am then using FormCollection form to access the form elements. from there I am unsure how I can access the items that have been submitted. I thought of using a for loop and then accessing them via something like form["Amount"][i] but obviously that is not going to work.

Am I going about this the right way and if so, does anyone have any suggestions about how this might work?

Thanks in advance.

doniyor
  • 36,596
  • 57
  • 175
  • 260
dave
  • 743
  • 2
  • 8
  • 20

6 Answers6

18

Old question, but still... You can get the posted values as an array by calling Request.Form.GetValues, or Request.QueryString.GetValues. For example:

string[] amounts = Request.Form.GetValues("Amount");

And the amounts array will contain the correct values, so you can post values containing comas, dots, whatever, and don't worry about splitting/parsing it.

Of course if you are running MVC, use the modelbinder to do it. But you can use this if you are using webforms, a generic handler, etc...

Akos Lukacs
  • 2,007
  • 1
  • 16
  • 21
11

Check out Model Binding To A List. Your Action method should be:

public ActionResult MyAction(string[] Amount, int[] Item){
   // ...
}

However this will make you need to "link" the items. Alternatively create a "Item" class:

public class Item {
    public string Amount { get; set; }
    public int Item { get; set; }
}

And

public ActionResult MyAction(IList<Item> items){
   // ...
}

And your markup should be:

<input type="hidden" name="items.Index" value="0" />
<input type="text" name="items[0].Amount" id="items[0].Amount">
   <select name="items[0].Item">
        <option value="1">Item 1"</option>
        <option value="2">Item 2"</option>
        <option value="3">Item 3"</option>
   </select>
<input type="hidden" name="items.Index" value="1" />
<input type="text" name="items[1].Amount" id="items[1].Amount">
   <select name="items[1].Item">
        <option value="1">Item 1"</option>
        <option value="2">Item 2"</option>
        <option value="3">Item 3"</option>
   </select>

Etc...

doniyor
  • 36,596
  • 57
  • 175
  • 260
veggerby
  • 8,940
  • 2
  • 34
  • 43
  • Thanks for the response, I did actually make a comment about doing this in Spencer's answer. It came down to JQuery not liking [] in the attribute id and name fields so when I went to change them, JQuery would not do this. Perhaps I should post about JQuery as it is a nicer way to do this. – dave Jan 13 '09 at 21:34
  • Awesome solution. Thank you. – Nileksh Dhimer Jan 06 '22 at 04:33
7

I believe if you have multiple fields named Amount the values will be comma delimited.

To access each one just try:

string[] amounts = Request.Form["Amount"].Split(new char[] { ',' });

Keep in mind though, the inputs are not cleaned on submission so if someone enters a comma into the text box it's going to cause issues.

Hence I'd recommend numbering them.

Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
  • That is correct, it just the accessing them that I am having difficulty with. – dave Jan 13 '09 at 04:39
  • Ah yeah you can use the split method. – Spencer Ruport Jan 13 '09 at 04:41
  • Ok, so maybe I am looking at the wrong area and I need to find out how to changed cloned form attributes that include [] characters! – dave Jan 13 '09 at 04:44
  • Well once they're in the amounts array you can iterate through them using a for loop like so: for(int i=0; i – Spencer Ruport Jan 13 '09 at 04:46
  • The only real issue is the someone adding a comma into the form field which I can take care of with validation. Do you think that doing it the way that I am currently is viable or would you recommend trying to get it working so that I number the form items? – dave Jan 13 '09 at 04:50
  • javascript validation should be fine. Honestly with HTTP forms anyone can screw up submissions if they really want to. Just protect your code accordingly and make sure that you don't accidentally access an array index that doesn't exist. – Spencer Ruport Jan 13 '09 at 05:07
  • Thanks Spencer, will report when I have finished trying to make this work! – dave Jan 13 '09 at 05:09
1

I ended up realising that (blush) the mechanism which JQuery uses to find the string within the cloned row (to replace) is basically regex. Thus I just needed to escape the square brackets and period. Once I did this I was able use JQuery to create form as Phil Haack's blog suggested.

Onto my next issue...!

dave
  • 743
  • 2
  • 8
  • 20
0

I would number them Amount1, Amount2, Amount3 etc.

Adam Pierce
  • 33,531
  • 22
  • 69
  • 89
  • The problem is that JQuery does not seem to like renaming a cloned form attribute when includes [] characters. The existing form element is cloned but the attributes id and name are not changed. Otherwise I would use this http://haacked.com/archive/0001/01/01/model-binding-to-a-list.aspx technique. – dave Jan 13 '09 at 04:42
0

You can change the id and name attribute of the input to something like this "Amount[1]","Amount[2]","Amount[3]" (yes, the id and name attribute can contain the special chars "[" or "]"). Then in the controller, write a http request parameter parser to get back the Amounts as collections.

jscoot
  • 2,019
  • 3
  • 24
  • 27