Comment accepter un tableau comme un ASP.NET paramètre D'action du contrôleur MVC?
j'ai un ASP.net contrôleur MVC appelé Designs
qui a une action avec la signature suivante:
public ActionResult Multiple(int[] ids)
cependant, quand j'essaie de naviguer vers cette action en utilisant l'url:
http://localhost:54119/Designs/Multiple?ids=24041,24117
le paramètre ids
est toujours nul. Y a-t-il un moyen d'amener MVC à convertir le paramètre de requête de L'URL ?ids=
en un tableau pour l'action? J'ai vu parler de l'utilisation d'un filtre d'actions, mais aussi loin que je peux dire que ne travaillez pour les messages où le tableau est passé dans les données de la requête plutôt que dans L'URL elle-même.
4 réponses
le modèle par défaut binder attend cette url:
http://localhost:54119/Designs/Multiple?ids=24041&ids=24117
afin de lier avec succès à:
public ActionResult Multiple(int[] ids)
{
...
}
et si vous voulez que cela fonctionne avec des valeurs séparées par des virgules, Vous pouvez écrire un classeur de modèle personnalisé:
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();
}
}
et alors vous pourriez appliquer ce modèle de reliure à un argument d'action particulier:
public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
...
}
ou l'appliquer globalement à tous les paramètres du tableau entier dans votre Application_Start
dans Global.asax
:
ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());
et maintenant votre action de contrôleur pourrait ressembler à ceci:
public ActionResult Multiple(int[] ids)
{
...
}
vous pouvez également utiliser ce format D'URL, et ASP.NET MVC fera tout pour vous. Mais, n'oubliez pas d'appliquer l'encodage D'URL.
?param1[0]=3344¶m1[1]=2222
pour étendre sur réponse de Darin Dimitrov , quelque chose que vous pouvez obtenir avec est d'accepter un simple string
dans votre paramètre URL et de le convertir en un tableau vous-même:
public ActionResult Multiple(string ids){
int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
/* ...process results... */
}
si vous obtenez une erreur d'analyse pendant que vous faites ceci (parce que quelqu'un vous a passé un tableau malformé), vous pouvez faire retourner une erreur 400 Bad Request
à la place de l'erreur par défaut, plus inamovible 404 Not Found
que MVC retourne quand un point de terminaison n'est pas trouvé.
Je ne sais pas d'où venait la chaîne D'URL de Groky, mais j'ai eu le même problème avec du javascript appelant mon controller/action. Il construirait une URL de null
, 1, ou de nombreux" IDs " à partir d'une liste de sélection multiple (ce qui est unique à la solution que je vais partager).
j'ai copié/collé le classeur modèle personnalisé de Darin et décoré mon action/paramètre, mais cela n'a pas fonctionné. J'ai toujours null
valorisé int[] ids
. Même dans le cas" sûr " où je en fait n'ont de nombreuses Id.
j'ai fini par changer le javascript pour produire un ASP.NET MVC friendly parameter array like
?ids=1&ids=2
j'ai dû faire quelques silly stuff, si la
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
donc, le bloc complet était
ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')
c'est bordélique, mais c'est la première fois que je dois pirater comme ça en javascript.