Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Model Binding to a collection where collection does not begin with a 0 index

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; }
}
like image 325
FloatLeft Avatar asked May 25 '12 19:05

FloatLeft


People also ask

What is bind property in MVC?

Model binding allows you map request parameters to actions. This means action methods will have one or more parameters and those parameters will receive their values from the model binding framework.


1 Answers

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.

like image 184
Darin Dimitrov Avatar answered Oct 15 '22 10:10

Darin Dimitrov