MVC Model Binding to a collection where collection does not begin with a 0 index
asp.net-mvc, asp.net-mvc-3, model-binding, validation
Solution
You could write a custom model binder:
public class ImeiNumberModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var modelName = bindingContext.ModelName;
var request = controllerContext.HttpContext.Request;
var paramName = request
.Params
.Keys
.Cast<string>()
.FirstOrDefault(
x => x.EndsWith(modelName, StringComparison.OrdinalIgnoreCase)
);
if (!string.IsNullOrEmpty(paramName))
{
return bindingContext
.ValueProvider
.GetValue(request[paramName])
.AttemptedValue;
}
return null;
}
}
and then apply it to the controller action:
public ActionResult IsImeiAvailable(
[ModelBinder(typeof(ImeiNumberModelBinder))] string imeiNumber
)
{
return Json(!string.IsNullOrEmpty(imeiNumber), JsonRequestBehavior.AllowGet);
}
Now the `ImeiGadgets[xxx]` part will be ignored from the query string.
Problem
I'm trying to perform remote validation on a property of an item within a collection. The validation works OK on the first item of the collection. The http request to the validation method looks like: ``` /Validation/IsImeiAvailable?ImeiGadgets[0].ImeiNumber=123456789012345 ``` However on the 2nd item where the url looks like below, the validation doesn't work ``` /Validation/IsImeiAvailable?ImeiGadgets[1].ImeiNumber=123456789012345 ``` Now I'm pretty sure the reason for this, is that binding wont work on a collection that doesn't begin with a zero index. My validation method has a signature as below: ``` public JsonResult IsImeiAvailable([Bind(Prefix = "ImeiGadgets")] Models.ViewModels.ImeiGadget[] imeiGadget) ``` Because I'm passing an item within a collection I have to bind like this yet what I'm really passing is just a single value. Is there anyway I can deal with this other than just binding it as a plain old query string. Thanks Edit: This is the quick fix to get the Imei variable but I'd rather use the model binding: ``` string imeiNumber = Request.Url.AbsoluteUri.Substring(Request.Url.AbsoluteUri.IndexOf("=")+1); ``` Edit: Here is my ImeiGadget class: ``` public class ImeiGadget { public int Id { get; set; } [Remote("IsImeiAvailable", "Validation")] [Required(ErrorMessage = "Please provide the IMEI Number for your Phone")] [RegularExpression(@"(\D*\d){15,17}", ErrorMessage = "An IMEI number must contain between 15 & 17 digits")] public string ImeiNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } ```