2012-02-29 9 views
58

Tengo un controlador de ASP.net MVC llamada Los diseños que tiene una acción con la siguiente firma:¿Cómo acepto una matriz como un parámetro de acción de controlador ASP.NET MVC?

public ActionResult Multiple(int[] ids) 

Sin embargo, cuando intento navegar a esta acción utilizando la url:

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

El El parámetro ids siempre es nulo. ¿Hay alguna manera de hacer que MVC convierta el parámetro de consulta? Ids = URL en una matriz para la acción? He visto hablar sobre el uso de un filtro de acción, pero hasta donde sé, eso solo funcionará para los POST donde el arreglo se pasa en los datos de solicitud en lugar de en la URL misma.

Respuesta

110

El modelo por defecto ligante espera que esta url:

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

a fin de obligar con éxito para:

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

Y si quieres que esto funcione con valores separados por comas se podría escribir un modelo personalizado carpeta:

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

y luego puede aplicar este modelo de carpeta a un particul argumento de la acción ar:

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

o aplicarlo a nivel mundial para todos los parámetros de matriz de enteros en su Application_Start en Global.asax:

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

y ahora su acción del controlador podría tener este aspecto:

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

Me faltaba '[FromUri]'. 'public ActionResult Multiple ([FromUri] int [] ids) {}' ** (GET) ** – C0d1ngJammer

+0

@Darin ¿hay alguna forma de aplicar el enlace personalizado globalmente pero simplemente ignorarlo para una acción específica? No pude encontrar una manera de hacerlo: https: //stackoverflow.com/questions/45379040/how-to-override-global-model-binder-for-speacific-post-action-mvc5 – akd

8

También puede usar este formato de URL y ASP.NET MVC hará todo por usted. Pero recuerde aplicar la codificación URL.

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

No sé donde cadena URL de Groky venía, pero no tenía el mismo problema con algunos javascript llamar a mi controlador/acción. Construiría una URL de null, 1 o muchos "ID" de una lista de selección múltiple (que es exclusiva de la solución que voy a compartir).

Copié/pegué el encuadernador de modelo personalizado de Darin y decoré mi acción/parámetro, pero no funcionó. Todavía tengo null con un valor de int[] ids. Incluso en el caso "seguro" donde realmente tenía muchas identificaciones.

que terminó cambiando el javascript para producir una serie de parámetros de usar ASP.NET MVC como

?ids=1&ids=2 

que tenía que hacer algunas cosas tontas, aunque

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 

Por lo tanto, el bloque completo era

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

Es complicado, pero es la primera vez que tuve que hackear esto en javascript.

+1

Simplemente curioso si hay un falta "no" antes de "primera vez" en esa última oración. De lo contrario, suerte de ti! – DCShannon

+1

@DCShannon: jaja, ¡veo tu punto! Pero, esta era mi primera vez. No estoy seguro de si este tipo de cosas es normal o si voy por la borda. –

7

Extender en Darin Dimitrov's answer, algo que puede salirse con la suya está aceptando un simple string en su parámetro de URL y convertirlo en una matriz a sí mismo:

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

Si se obtiene un error de análisis al hacer esto (porque alguien le pasó una matriz con formato incorrecto), puede hacer que su controlador de excepción devuelva un error 400 Bad Request en lugar del error 404 Not Found predeterminado más antipático que MVC devuelve cuando no se encuentra un punto final.

Cuestiones relacionadas