Here is a model binder that I did for you and does what you want. It by no means complete (no validation, no error checking etc), but it can kick start you. One thing I particularly dislike is that the ModelBinder directly accesses the form collection instead of using the ValueProvider of the context, but the latter doesn't let you get all bindable values.
public class AutoCompleteItemModelBinder : IModelBinder
{
// Normally we would use bindingContext.ValueProvider here, but it doesn't let us
// do pattern matching.
public object BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string pattern = @"tag\[(?<Key>.*)\]";
if (!String.IsNullOrWhiteSpace (bindingContext.ModelName))
pattern = bindingContext.ModelName + "." + pattern;
IEnumerable<string> matchedInputNames =
controllerContext.HttpContext.Request.Form.AllKeys.Where(inputName => Regex.IsMatch(inputName, pattern, RegexOptions.IgnoreCase));
return matchedInputNames.Select (inputName =>
new AutoCompleteItem {
Value = controllerContext.HttpContext.Request.Form[inputName],
Key = Regex.Match(inputName, pattern).Groups["Key"].Value
}).ToList();
}
}
Here is a sample action that uses it:
[HttpPost]
public void TestModelBinder ([ModelBinder(typeof(AutoCompleteItemModelBinder))]
IList<AutoCompleteItem> items)
{
}
And a sample view. Note the "items." prefix - it's the Model Name (you can drop it depending on how you submit this list of items:
@using (Html.BeginForm ("TestModelBinder", "Home")) {
<input type="text" name="items.tag[15-d]" value="Little Owl" />
<input type="text" name="items.tag[19-a]" value="Merlin" />
<input type="submit" value="Submit" />
}
If you have questions - add a comment and I will expand this answer.