Alexander
Alexander

Reputation: 20244

Multiple parameters by the same name

Consider the following ApiController:

public class SomeController : ApiController
{
    [HttpGet]
    public class SomeFunction(int someVal = 0) {
        ...
    }
}

This works as expected:

http://myserver/myApp/Some/SomeFunction?someVal=0

but I have issues with this function when it is called it with

http://myserver/myApp/Some/SomeFunction?someVal=0&someVal=0

and now I try to understand what's happening then and there. I get no error message, but the output of the function is not as expected.

Upvotes: 3

Views: 5351

Answers (2)

Derek Winfield
Derek Winfield

Reputation: 31

In asp.net core, you can simply make the parameter an array to accept multiple querystring values of the same name. for example a querystring with ?country=GB&country=DE&country=IT will be properly bound to a method parameter defined as string[] country.

Upvotes: 3

JotaBe
JotaBe

Reputation: 39055

Web API parameter binding is not able to convert several parameters from the query string into an array, so you have to two options:

  • customize the parameter binding
  • manually access and convert the query string parameters

The second option includes getting the query string name-value pairs, and parsing them yourself. To get the name value pairs, use this:

Request.GetQueryNameValuePairs()

To extract the int values, you can do something like this:

var values= Request.GetQueryNameValuePairs()
  .Where(kvp => kvp.Key == "someVal")
  .Select(kvp => int.Parse(kvp.Value))
  .ToArray();

Of course, you should control errors on the parsing and so on. This is a basic sample code.

This is an implementation of a model binder for the first option:

public class IntsModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof (Ints))
        {
            return false;
        }
        var intValues = actionContext.Request.GetQueryNameValuePairs()
            .Where(kvp => kvp.Key == bindingContext.ModelName)
            .Select(kvp => int.Parse(kvp.Value))
            .ToList();
        bindingContext.Model = new Ints {Values = intValues};
        return true;
    }
}

Again, this is a basic implementation that, between other things, lacks the control of errors.

This is one of the ways to use it in an action, but, please, read the link on parameter binding to see other (better) ways of using it:

// GET api/Test?keys=1&keys=7
public string Get([ModelBinder(typeof(IntsModelBinder))]Ints keys)
{
    return string.Format("Keys: {0}", string.Join(", ", keys.Values));
}

Upvotes: 5

Related Questions