How do I accept an array as an ASP.NET MVC controller action parameter?

后端 未结 5 781
遥遥无期
遥遥无期 2020-11-27 13:06

I have an ASP.net MVC controller called Designs that has an action with the following signature:

public ActionResult Multiple(int[] ids)
         


        
相关标签:
5条回答
  • 2020-11-27 13:37

    To extend on Darin Dimitrov's answer, something you can get away with is accepting a simple string in your URL parameter and converting it to an array yourself:

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

    If you get a parse error while doing this (because someone passed you a malformed array), you can cause your exception handler to return a 400 Bad Request error instead of the default, more unfriendly 404 Not Found error that MVC returns when an endpoint is not found.

    0 讨论(0)
  • 2020-11-27 13:38

    The default model binder expects this url:

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

    in order to successfully bind to:

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

    And if you want this to work with comma separated values you could write a custom model binder:

    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();
        }
    }
    

    and then you could apply this model binder to a particular action argument:

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

    or apply it globally to all integer array parameters in your Application_Start in Global.asax:

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

    and now your controller action might look like this:

    public ActionResult Multiple(int[] ids)
    {
        ...
    }
    
    0 讨论(0)
  • 2020-11-27 13:38

    I don't know where Groky's URL string was coming from, but I had the same problem with some javascript calling my controller/action. It would build up a URL of null, 1, or many "IDs" from a multiple-select list (which is unique to the solution I'm going to share).

    I copy/pasted Darin's custom model binder and decorated my action/parameter, but it didn't work. I still got null valued int[] ids. Even in the "safe" case where I actually did have many IDs.

    I ended up changing the javascript to produce an ASP.NET MVC friendly parameter array like

    ?ids=1&ids=2
    

    I had to do some silly stuff, though

    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
    

    So, the full block was

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

    It's messy, but it's the first time I had to hack like this in javascript.

    0 讨论(0)
  • 2020-11-27 13:50

    You can also use this URL format, and ASP.NET MVC will do everything for you. But, remember to apply URL encoding.

    ?param1[0]=3344&param1[1]=2222
    
    0 讨论(0)
  • 2020-11-27 13:56

    .Net Core Answer

    For those coming here in recent times, you can do this in .Net Core with:

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

    and:

    public ActionResult Multiple([FromQuery] int[] ids)
    {
        ...
    }
    
    0 讨论(0)
提交回复
热议问题