【问题标题】:How do I accept an array as an ASP.NET MVC controller action parameter?如何接受数组作为 ASP.NET MVC 控制器操作参数?
【发布时间】:2012-03-19 11:29:19
【问题描述】:

我有一个名为 Designs 的 ASP.net MVC 控制器,它有一个带有以下签名的操作:

public ActionResult Multiple(int[] ids)

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

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

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

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3 routes


    【解决方案1】:

    .Net 核心答案

    对于最近来到这里的人,您可以在 .Net Core 中使用:

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

    和:

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

    【讨论】:

      【解决方案2】:

      要扩展 Darin Dimitrov's answer,您可以在 URL 参数中接受一个简单的 string 并自己将其转换为数组:

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

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

      【讨论】:

        【解决方案3】:

        我不知道 Groky 的 URL 字符串是从哪里来的,但是我在调​​用我的控制器/动作的一些 javascript 时遇到了同样的问题。它将从多选列表中构建一个null、1 或许多“ID”的 URL(这是我要分享的解决方案所独有的)。

        我复制/粘贴了 Darin 的自定义模型活页夹并装饰了我的动作/参数,但它不起作用。我仍然得到null 重视int[] ids。即使在我确实有很多 ID 的“安全”情况下。

        我最终更改了 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 中这样破解。

        【讨论】:

        • 只是好奇最后一句中“第一次”之前是否缺少“不”。否则,你很幸运!
        • @DCShannon:哈哈,我明白你的意思了!但是,这是我的第一次。我不确定这种事情是正常的还是我过火了。
        【解决方案4】:

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

        ?param1[0]=3344&param1[1]=2222
        

        【讨论】:

          【解决方案5】:

          默认模型绑定器需要这个 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 in Global.asax 中的所有整数数组参数:

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

          现在您的控制器操作可能如下所示:

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

          【讨论】:

          • 我错过了[FromUri]public ActionResult Multiple([FromUri]int[] ids) {} (GET)
          • @Darin 有没有办法全局应用自定义绑定但忽略特定操作?我找不到这样做的方法:stackoverflow.com/questions/45379040/…
          猜你喜欢
          • 2014-02-21
          • 2011-02-14
          • 1970-01-01
          • 2023-03-24
          • 2019-05-10
          • 2011-07-25
          • 1970-01-01
          • 1970-01-01
          • 2022-01-11
          相关资源
          最近更新 更多