動的な数のフォーム要素を持つ ASP.NET MVC を使用してフォームを作成するとします。
たとえば、商品ごとにチェックボックスが必要で、商品の数は日々変化します。
コントローラーにポストされたフォーム データをどのように処理しますか? 返されるフォーム値の数がわからないため、アクション メソッドにパラメーターを設定することはできません。
動的な数のフォーム要素を持つ ASP.NET MVC を使用してフォームを作成するとします。
たとえば、商品ごとにチェックボックスが必要で、商品の数は日々変化します。
コントローラーにポストされたフォーム データをどのように処理しますか? 返されるフォーム値の数がわからないため、アクション メソッドにパラメーターを設定することはできません。
各チェックボックスに一意の名前の値を与えるだけです:
<input class="approveCheck" id="<%= "approveCheck" + recordId %>"
name="<%= "approveCheck" + recordId %>" type="checkbox" />
送信後、アクション内のフォーム値のリストを解析します。
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);
// ...
フォームの値を引数として渡す必要はありません。Request.Form から取得できます。
もう 1 つのオプション: モデル バインダーを記述して、リストをフォーム送信用のカスタム タイプに変更します。
クレイグの答えによると..それはより安全です。複数のフォーム要素を同じ名前で投稿することには癖があります。コントロールの「コレクション」を作成するロジックを、WebForms と同様の方法でラップすることが賢明であると付け加えておきます。Web フォームは、コンテナー コントロールの名前を先頭に追加し、インデックスを追加します。たとえば、Repeater では、内部のフォーム要素に名前が付けられます (たとえば、RepeaterName_Element1、RepeaterName_Element2 など)。要素を取り出すときは、FindControl などを使用する必要があります。
使用しているバインダーに応じて、これは機能するはずです。
<%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/>
<%}%>
...これは、次のような HTML になります (名前の配列表記に注意してください)。
<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
...そして投稿を処理するコントローラーメソッド:
public ActionResult SelectProducts(IList<ProductSelection> products)
{
...
}
バインドすると、products パラメータには ProductSelection の 2 つのインスタンスが含まれます。
1 つの注意点は、複雑なオブジェクトに対して新しい既定のバインドを使用していないことです。むしろ、MvcContrib の NameValueDeserializer または CastleBind を使用しています。どちらもこのように動作します。ベータ版でのバインドも同じように機能すると思います。
データに応じて、「CheckboxList」を出力して (これは新しいバージョンでは不可能になりました)、string[]
パラメーターを使用するか、複数のフォームを設定してアクションを変更することができます。