Scenario
You want to build on the client-side a list of structured items (for example a list of Shopping Cart Items with each item having a Product ID and a Quantity). Then you want to post this list to an ASP.NET MVC action using a single HTTP request.
Server-Side Code
You start by defining a model class that represents an item of the list.
public class ShoppingCartItem
{
public int ProductID { get; set; }
public int Quantity { get; set; }
}
Then you define an action method that takes as argument an array of items.
[HttpPost]
public ActionResult Index(ShoppingCartItem[] items)
{
// Process the shopping cart items here.
}
Client-Side Code
@{ Html.BeginForm(); }
<input type="hidden" name="items[0].ProductID" value="102" />
<input type="hidden" name="items[0].Quantity" value="1" />
<input type="hidden" name="items[1].ProductID" value="103" />
<input type="hidden" name="items[1].Quantity" value="3" />
<input type="hidden" name="items[2].ProductID" value="104" />
<input type="hidden" name="items[2].Quantity" value="2" />
<input type="submit" value="Post list" />
@{ Html.EndForm(); }
If the above form is posted to the Index action method we defined earlier, the key-value pairs will be translated on the server to a ShoppingCartItem array with 3 elements.
But it is usually not that easy. You will probably want to add and remove items dynamically on the client-side using JavaScript before posting the form. Here is how to do it: Start by creating the form that will be used to post the list of items.
@{ Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "cart-items-form" }); }
@{ Html.EndForm(); }
And define the template for the HTML element that will represent an item.
var cartItemTemplate =
'<div id="cart-item-{itemID}" class="cart-item">' +
' <input type="hidden" name="items[i].ProductID" value="{productID}" />' +
' <input type="hidden" name="items[i].Quantity" value="{quantity}" />' +
'</div>';
Now the methods to add and remove items. The method that adds an item returns an ID that can be used later to remove the item.
function addCartItem(productID, quantity) {
var cartItemHtml = cartItemTemplate.replace('{itemID}', currentItemID)
.replace('{productID}', productID)
.replace('{quantity}', quantity);
$(cartItemHtml).appendTo('#cart-items-form');
return currentItemID++;
}
function removeCartItem(itemID) {
$('#cart-items-form').children('#cart-item-' + itemID).remove();
}
And right before posting the form, replace the [i] in the names by the actual item indices.
$(function () {
$('#cart-items-form').submit(
function () {
$(this).children('.cart-item').each(
function (cartItemIndex, cartItemElement) {
$(cartItemElement).children().each(
function () {
var newName = $(this).attr('name').replace('[i]', '[' + cartItemIndex + ']');
$(this).attr('name', newName)
}
);
}
);
}
);
});