Proper submission of forms with autogenerated controls

Go To StackoverFlow.com

0

Based on: MVC Html.CheckBox and form submit issue

Let's consider following example. View:

   <% using(Html.BeginForm("Retrieve", "Home")) %>
       <% { %>
    <%foreach (var app in newApps)              { %>  
  <tr> 
       <td><%=Html.CheckBox(""+app.ApplicationId )%></td>      

   </tr>  
<%} %>
 <input type"submit"/>
<% } %>

Controller:

 List<app>=newApps; //Database bind
 for(int i=0; i<app.Count;i++)
 {

    var checkbox=Request.Form[""+app[i].ApplicationId];
    if(checkbox!="false")// if not false then true,false is returned
 }

Proposed solution was about manual parsing of Request.Form that seems for me out of MVC concept. It makes the problem while unit testing of this controller method. In this case I need to generate mock Request.Form object instead of some ViewModel passed as input param.

Q: Is there some other solution of submitting forms like this, so that ViewModel object, containing collection of submitted controls, passed as input param to controller method?

For example:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Retrieve(AppList[] applist) 

or

public ActionResult Retrieve(AppList<App> applist) 

etc

2009-06-16 08:38
by Andriy Tkach
Andrey, I have posted another solution. Try it - eu-ge-ne 2009-06-17 20:04


0

Controller:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Retrieve(AppList[] applist)

View:

<% using(Html.BeginForm("Retrieve", "Home")) %> { %>
    <%foreach (var app in newApps) { %>
    <tr>
        <td><%=Html.CheckBox(String.Format("appList[{0}].AProperty", app.ApplicationId) %></td>
    </tr>
    <% } %>
    <input type"submit" />
<% } %>

Read this: Scott Hanselman's ComputerZen.com - ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

UPDATED:

If ApplicationId is a key from DB it is better to use AppList<App> as Action parameter. Then your form would be looking as:

<% using(Html.BeginForm("Retrieve", "Home")) %> { %>
<% var counter = 0; %>
    <% foreach (var app in newApps) { %>
    <tr>
        <td><%=Html.CheckBox(String.Format("appList[{0}].Key", counter), app.ApplicationId) %></td>
        <!-- ... -->
        <td><%=Html.Input(String.Format("appList[{0}].Value.SomeProperty1", counter), app.SomeProperty1) %></td>
        <td><%=Html.Input(String.Format("appList[{0}].Value.SomePropertyN", counter), app.SomePropertyN) %></td>
        <% counter = counter + 1; %>
    </tr>
    <% } %>
    <input type"submit" />
<% } %>
2009-06-16 10:09
by eu-ge-ne
It seems like stuff I needed, but for now I did not succeed in it. 1. I found that if app.ApplicationId is not ordered and there are holes. since it is db key (example 1, 2, 5, 11) applist param comes to controller as null. If I take some iterated key like <%i++;%> it works. 2. Second problem is that it submots to form (of course) all objects even if checkbox is not checked. Adding some additnional field to model to indicate whether such a record was chosen seems for me not very good idea - Andriy Tkach 2009-06-16 23:39
Yes, I did the same way by adding counter; Second problem was resolved by moving checkboxses state in separate array parameter. controller checks whether this state is true then add model object to db. Thank you for navigation - Andriy Tkach 2009-06-17 21:55