Как принять массив в качестве параметра действия контроллера ASP.NET MVC?
У меня есть ASP.net MVC-контроллер, называемый Designs, который имеет действие со следующей подписью:
public ActionResult Multiple(int[] ids)
Однако, когда я пытаюсь перейти к этому действию с помощью URL:
http://localhost:54119/Designs/Multiple?ids=24041,24117
Параметр ids всегда равен нулю. Есть ли способ получить MVC для преобразования параметра? Ids = URL-запроса в массив для действия? Я видел разговоры об использовании фильтра действий, но насколько я могу судить, это будет работать только для POST, где массив передается в данных запроса, а не в самом URL-адресе.
Ответы
Ответ 1
Связующее устройство по умолчанию ожидает этот 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)
{
...
}
Ответ 2
Вы также можете использовать этот формат URL, и ASP.NET MVC сделает все для вас. Но не забудьте применить кодировку URL.
?param1[0]=3344¶m1[1]=2222
Ответ 3
Чтобы продлить на Дарин Димитров ответ, вы можете уйти от того, чтобы принять простой string
в свой URL-адрес и преобразовать его в массив самостоятельно:
public ActionResult Multiple(string ids){
int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
/* ...process results... */
}
Если при этом вы получите ошибку синтаксического анализа (потому что кто-то передал вам неверный массив), вы можете заставить обработчик исключений возвращать ошибку 400 Bad Request
вместо дефолтной, более недружелюбной ошибки 404 Not Found
, возвращаемой MVC, когда конечная точка не найдена.
Ответ 4
Я не знаю, откуда взялась строка URL Groky, но у меня была такая же проблема с некоторым javascript, вызывающим мой контроллер/действие. Он создаст URL-адрес null
, 1 или многих "идентификаторов" из списка множественного выбора (который уникален для решения, которое я собираюсь предоставить).
Я скопировал/вставлял связующее устройство для модели Darin и украсил мое действие/параметр, но это не сработало. Я все еще получил 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.