I have two view models, one aggregating a collection of the other:
class Parent
{
public string Key { get; set; }
public IList<Child> Children { get; set; }
}
class Child
{
public string Key { get; set; }
[Required, Remote("VerifyNameUnique", "Parent", AdditionalFields = "Key", ErrorMessage = "The name must be unique.")]
public string Name { get; set; }
}
I have a controller action
public ActionResult VerifyNameUnique(string key, string name)
{
var result = // ... verify uniqueness
return Json(result, JsonRequestBehavior.AllowGet);
}
And a view:
@model Parent
@Html.HiddenFor(m => m.Key)
@for(var i=0; i<Model.Children; i++)
{
@Html.HiddenFor (m => m.Children[i].Key)
@Html.LabelFor(m => m.Children[i].Name)
@Html.EditorFor (m => m.Children[i].Name)
}
When my Parent/Child editor template calls the action to validate any of the Name fields, it sends a querystring ?Children[0].Key=abc&Children[0].Name=Fred, where 0 is the index i of the child just edited.
That doesn’t bind to the parameters of VerifyNameUnique because of the prefix. I have tried using BindAttribute with a prefix set, but the prefix varies by the value of i.
Writing a custom model binder is an option but seems like overkill right now for this simple scenario. Is there anything nicer I can do?
This simply is not supported. So you will have to either write a custom model binder or a custom Remote validation attribute. This being said, what you are trying to achieve is probably not a very good idea because if the user clicks on the submit button an AJAX request will be sent for every field in the collection which is not very efficient. I would probably go with a custom remote validation field directly on the collection property on the parent in order to validate everything with a single roundtrip to the server.