Как принять массив в качестве параметра действия контроллера ASP.NET MVC? - PullRequest
75 голосов
/ 01 марта 2012

У меня есть контроллер ASP.net MVC с именем Designs, который выполняет действие со следующей подписью:

public ActionResult Multiple(int[] ids)

Однако, когда я пытаюсь перейти к этому действию, используя URL:

http://localhost:54119/Designs/Multiple?ids=24041,24117

Параметр ids всегда равен нулю.Есть ли способ заставить MVC преобразовать параметр запроса URL-адреса ?ids= в массив для действия?Я видел разговоры об использовании фильтра действий, но насколько я могу судить, он будет работать только для тех POST, где массив передается в данных запроса, а не в самом URL.

Ответы [ 4 ]

135 голосов
/ 01 марта 2012

Связыватель модели по умолчанию ожидает этот URL:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

, чтобы успешно связать с:

public ActionResult Multiple(int[] ids)
{
    ...
}

И если вы хотите, чтобы это работало со значениями, разделенными запятыми, вы можете написать пользовательское связующее звено модели:

public class IntArrayModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (value == null || string.IsNullOrEmpty(value.AttemptedValue))
        {
            return null;
        }

        return value
            .AttemptedValue
            .Split(',')
            .Select(int.Parse)
            .ToArray();
    }
}

и затем вы можете применить эту модель связывания к конкретному аргументу действия:

public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
    ...
}

или примените его глобально ко всем параметрам целочисленного массива в Application_Start в Global.asax:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());

и теперь действие вашего контроллера может выглядеть так:

public ActionResult Multiple(int[] ids)
{
    ...
}
12 голосов
/ 03 мая 2016

Если продолжить Ответ Дарина Димитрова , то, что вы можете сойти с рук, - это просто принять string в параметре URL и преобразовать его в массив самостоятельно:

public ActionResult Multiple(string ids){
  int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
  /* ...process results... */
}

Если во время этого вы получаете ошибку разбора (потому что кто-то передал вам некорректный массив), вы можете заставить свой обработчик исключений возвращать ошибку 400 Bad Request вместо значения по умолчанию, более недружелюбную ошибку 404 Not Found, которую MVC возвращает, когда конечная точкане найден.

9 голосов
/ 28 ноября 2012

Вы также можете использовать этот формат URL, и ASP.NET MVC сделает все за вас.Но не забудьте применить кодировку URL.

?param1[0]=3344&param1[1]=2222
5 голосов
/ 19 сентября 2013

Я не знаю, откуда взялась строка URL Groky, но у меня была та же проблема с некоторым JavaScript, вызывающим мой контроллер / действие. Он будет создавать URL-адрес null, 1 или многих «идентификаторов» из списка с множественным выбором (что является уникальным для решения, которым я собираюсь поделиться).

Я скопировал / вставил пользовательскую подшивку модели Дарина и украсил свое действие / параметр, но это не сработало. Я все еще получил null оцененный int[] ids. Даже в «безопасном» случае, когда у меня действительно было много идентификаторов.

Я закончил тем, что изменил javascript для создания массива параметров ASP.NET MVC вроде

?ids=1&ids=2

Я должен был делать глупости, хотя

ids || []                 #=> if null, get an empty array
[ids || []]               #=> if a single item, wrap it in an array
[].concat.apply([], ...)  #=> in case I wrapped an array, flatten it

Итак, полный блок был

ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')

Это грязно, но мне впервые пришлось так взламывать в javascript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...