如何接受数组作为ASP.NET MVC控制器操作参数?

Gro*_*kys 78 asp.net-mvc-3

我有一个ASP.net MVC控制器调用Designs,具有以下签名的操作:

public ActionResult Multiple(int[] ids)
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用url导航到此操作时:

http://localhost:54119/Designs/Multiple?ids=24041,24117
Run Code Online (Sandbox Code Playgroud)

ids参数始终为null.有没有办法让MVC将?ids=URL查询参数转换为动作的数组?我已经看到过使用动作过滤器的讨论,但据我所知,这只适用于在请求数据中而不是在URL本身中传递数组的POST.

Dar*_*rov 141

默认模型绑定器需要此URL:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117
Run Code Online (Sandbox Code Playgroud)

为了成功绑定到:

public ActionResult Multiple(int[] ids)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果您希望使用逗号分隔值,您可以编写自定义模型绑定器:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以将此模型绑定器应用于特定的操作参数:

public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

或全局应用到所有的整数数组参数Application_StartGlobal.asax:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());
Run Code Online (Sandbox Code Playgroud)

现在你的控制器动作可能如下所示:

public ActionResult Multiple(int[] ids)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 我缺少`[FromUri]`。`public ActionResult Multiple([FromUri] int [] ids){}`**(GET)** (2认同)

The*_*tor 13

为了扩展Darin Dimitrov的答案,你可以通过接受stringURL参数中的简单并自己将其转换为数组:

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

如果在执行此操作时遇到解析错误(因为有人向您传递了格式错误的数组),您可以使异常处理程序返回400 Bad Request错误,而不是在404 Not Found找不到端点时MVC返回的默认,更不友好的错误.


Cio*_*eru 9

您也可以使用此URL格式,ASP.NET MVC将为您完成所有操作.但是,请记住应用URL编码.

?param1[0]=3344&param1[1]=2222
Run Code Online (Sandbox Code Playgroud)


Red*_*Red 8

.Net Core 答案

对于最近来到这里的人,您可以在 .Net Core 中使用以下命令执行此操作:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117
Run Code Online (Sandbox Code Playgroud)

和:

public ActionResult Multiple([FromQuery] int[] ids)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)


Ant*_*ean 6

我不知道Groky的URL字符串来自哪里,但我遇到了一些javascript调用我的控制器/动作的问题.它将null从多选列表中构建一个,一个或多个"ID" 的URL (这对我要分享的解决方案是唯一的).

我复制/粘贴了Darin的自定义模型绑定器并装饰了我的动作/参数,但它没有用.我仍然很有null价值int[] ids.即使在"安全"的情况下,我确实有很多ID.

我最终改变了javascript以生成一个ASP.NET MVC友好的参数数组

?ids=1&ids=2
Run Code Online (Sandbox Code Playgroud)

不过,我不得不做一些愚蠢的事情

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
Run Code Online (Sandbox Code Playgroud)

所以,完整的块是

ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')
Run Code Online (Sandbox Code Playgroud)

它很乱,但这是我第一次在javascript中破解这样的东西.

  • 只是想知道最后一句话中的“第一次”之前是否缺少“不”。否则,你有福了! (2认同)