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; } } ```

Original source