0

I've been trying to pass an array of int's created by the following function:

function getCurrentSwimmerList() {
    var swimmerList = [];
    $("#swimmerTable >  tbody > tr").each(function () {
        swimmerList.push( parseInt($(this).data('swimmerid')) );
    });
    return swimmerList;
}

Which I use in token-input to eliminate ceartin suggestions from the search box, so I've set up token-input up like so:

$("#swimmerTokenInput").tokenInput("Admin/retrieveTokensForQuery", {
            urlParams: { "IDsAlreadyAdded": getCurrentSwimmerList },

I modified the token-input file to allow you to pass additional paramters in a request by setting urlParams, the addition I made to the code was (in the appropriate section):

//add params passed in as urlParams
if (settings.urlParams != null) {
    for (var key in settings.urlParams) {
        if (settings.urlParams.hasOwnProperty(key)) {
            ajax_params.data[key] = settings.urlParams[key];
        }
    }
}

I tested and I successfully get these values in the query string (where Ol was typed into the search box):

IDsAlreadyAdded=5%2C6&q=Ol

Which chrome recognizes and parses correctly:

IDsAlreadyAdded:5,6
q:Ol

The signature of the method I'm calling is as follows:

public JsonResult retrieveTokensForQuery(string q, int[] IDsAlreadyAdded)

Each time q successfully get's the appropriate value, however IDsAlreadyAdded always gets a null value. I've looked at various answers on SO (trying traditional=true, or IdsAlreadyAdded[] = ..., having List<int> or IEnumerable<int>) to try fix the problem, but I couldn't get it to work.

Any help would be greatly appreciated.

1 Answer 1

1

You could always create a custom model binder that maps the string value to an int[] like this:

public class IntArrayModelBinder : System.Web.Mvc.DefaultModelBinder
{
    public override object BindModel(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (!string.IsNullOrEmpty(valueProviderResult.AttemptedValue))
        {
            var items = valueProviderResult.AttemptedValue.Split(',');
            var result = new int[items.Length];
            for (var counter = 0; counter < items.Length; counter++)
            {
                result[counter] = int.Parse(items[counter]);
            }
            return result;
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

and then just register the binder when you initialise your routing:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());
Sign up to request clarification or add additional context in comments.

3 Comments

how do I register the model-binder to a specific route?
Custom model binders are mapping helpers for MVC when MVC is unable to figure out how to bind a specific type. Any time MVC sees a route with an int[] parameter, it will first attempt to parse the value using the custom binder above. So, this basically binds it for every route with an int[] parameter.
Your solution works perfectly, I had to edit it slightly though, I changed one line to result[counter] = int.Parse(items[counter]); was needed, otherwise the array was populated with 0s by default. cheers :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.