Here's one technique that you could use to achieve this.
Let's start with the view model:
public class ViewModel
{
public DateTime SomeDate { get; set; }
public string SomeString { get; set; }
public List<E> SomeList { get; set; }
}
public class E
{
public bool Selected { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
}
then we write some controller to handle the rendering of the view and the AJAX request:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new ViewModel
{
SomeDate = DateTime.Now,
SomeString = "some text",
SomeList = Enumerable.Range(1, 7).Select(x => new E
{
Foo = "foo " + x,
Bar = "bar " + x
}).ToList()
};
return View(model);
}
[HttpPost]
public ActionResult Index(ViewModel model)
{
// Here we will get our view model properly bound and
// the list will contain only the items that the user
// has selected (see below...)
// TODO: do some processing
return Content("Thanks for submitting this data", "text/plain");
}
}
then we move on to the ~/Views/Home/Index.cshtml
view:
@model ViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.SomeDate)
@Html.EditorFor(x => x.SomeDate)
</div>
<div>
@Html.LabelFor(x => x.SomeString)
@Html.EditorFor(x => x.SomeString)
</div>
<table>
<thead>
<tr>
<th></th>
<th>Foo</th>
<th>Bar</th>
</tr>
</thead>
<tbody>
@Html.EditorFor(x => x.SomeList)
</tbody>
</table>
<input type="submit" value="Send selected values to server using AJAX" />
}
and finally we define an Editor template for the E
type (~/Views/Home/EditorTemplates/E.cshtml
) which will be rendered for each element of the collection:
@{
var index = Guid.NewGuid().ToString();
var prefix = Regex.Replace(ViewData.TemplateInfo.HtmlFieldPrefix, @"[d+]$", match =>
{
return string.Format("[{0}]", index);
});
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
<input type="hidden" name="SomeList.Index" value="@index" />
<tr>
<td>
@Html.DisplayFor(x => x.Foo)
@Html.HiddenFor(x => x.Foo)
</td>
<td>
@Html.DisplayFor(x => x.Bar)
@Html.HiddenFor(x => x.Bar)
</td>
<td>
@Html.CheckBoxFor(x => x.Selected)
</td>
</tr>
OK, so at this stage we haven't yet written the javascript part so this should behave as a normal HTML form and when it is submitted it will send all the values to the server.
And final piece would be to AJAXify the form and POST only the records that the user selected in the request. So we could do this in a separate javascript file:
$(function () {
$('form').submit(function () {
// we clone the original form and we will
// filter out the non-selected fields
var myForm = $(this).clone(false, false);
$('tr', myForm).each(function () {
var isSelected = $(':checkbox', this).is(':checked');
if (!isSelected) {
$(this).remove();
}
});
$.ajax({
url: this.action,
type: this.method,
data: myForm.serialize(),
success: function (result) {
alert(result);
}
});
return false;
});
});
As a good article for handling dynamic lists I would recommend you the following blog post.