ASP.NET MVC: pasar parámetros al controlador

105

Tengo un controlador con un método de acción de la siguiente manera:

public class InventoryController : Controller
{
    public ActionResult ViewStockNext(int firstItem)
    {
        // Do some stuff
    }
}

Y cuando lo ejecuto, aparece un error que indica:

El diccionario de parámetros no contiene un valor válido de tipo 'System.Int32' para el parámetro 'firstItem'. Para hacer que un parámetro sea opcional, su tipo debe ser un tipo de referencia o un tipo que acepta valores NULL.

Lo tuve funcionando en un momento y decidí probar la función sin parámetros. Al descubrir que el controlador no era persistente, volví a colocar el parámetro, ahora se niega a reconocer el parámetro cuando llamo al método.

Estoy usando esta sintaxis de URL para llamar a la acción:

http://localhost:2316/Inventory/ViewStockNext/11

¿Alguna idea de por qué obtendría este error y qué debo hacer para solucionarlo?

Intenté agregar otro método que toma un número entero a la clase y también falla por la misma razón. Intenté agregar uno que toma una cadena, y la cadena está configurada como nula. Intenté agregar uno sin parámetros y funciona bien, pero por supuesto no se adapta a mis necesidades.

Impar
fuente

Respuestas:

106

Su enrutamiento debe configurarse siguiendo las líneas de {controller}/{action}/{firstItem}. Si dejó el enrutamiento como predeterminado {controller}/{action}/{id}en su global.asax.csarchivo, deberá pasar id.

routes.MapRoute(
    "Inventory",
    "Inventory/{action}/{firstItem}",
    new { controller = "Inventory", action = "ListAll", firstItem = "" }
);

... O algo parecido a eso.

Jarrett Meyer
fuente
44
O simplemente cambie el nombre de "firstItem" a "id"
Kyle Trauberman
8
Además de que el mundo sea aconsejable agregar un objeto de restricciones a la MapRoute, así: new { firstItem = @"\d" }. De esta forma solo aceptará si el parámetro es cualquier tipo de número. Puede modificar la expresión regular a su gusto, e incluso limitar el número de decimales, así: new { firstItem = @"\d{4}" }- ahora solo puede tener 4 números. Editar: ejemplo de MapRoute completamente modificado: jsfiddle.net/HJRgT
KristianB
86

puedes cambiar firstItem a id y funcionará

puede cambiar el enrutamiento en global.asax (no lo recomiendo)

y no puedo creer que nadie haya mencionado esto, puedes llamar a:

http://localhost:2316/Inventory/ViewStockNext?firstItem=11

En una @ Url.Action sería:

@Url.Action("ViewStockNext", "Inventory", new {firstItem=11});

dependiendo del tipo de lo que estés haciendo, la última será más adecuada. También debería considerar no realizar la acción ViewStockNext y en su lugar una acción ViewStock con index. (mis 2 centavos)

Bart Calixto
fuente
15

Para reformular la respuesta de Jarret Meyer , debe cambiar el nombre del parámetro a 'id' o agregar una ruta como esta:

routes.MapRoute(
        "ViewStockNext", // Route name
        "Inventory/ViewStockNext/{firstItem}",  // URL with parameters
        new { controller = "Inventory", action = "ViewStockNext" }  // Parameter defaults
    );

El motivo es que la ruta predeterminada solo busca acciones sin parámetro o con un parámetro llamado 'id'.

Editar: Je, no importa, Jarret agregó un ejemplo de ruta después de la publicación.

Matt Mitchell
fuente
8

o hazlo con el atributo de ruta:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}
Yar
fuente
Es posible que esta propiedad no funcione con versiones anteriores de MVC.
Suat Atan PhD
Además, para que esto funcione, debe asegurarse de haber llamado routes.MapMvcAttributeRoutes();dentro del RegisterRoutes(RouteCollection)método de la aplicación (generalmente con scaffolding en App_Start \ RouteConfig.cs). Puede que no esté allí de forma predeterminada.
Daniel Scott
7

Headspring creó una bonita biblioteca que le permite agregar alias a sus parámetros en los atributos de la acción. Esto se ve así:

[ParameterAlias("firstItem", "id", Order = 3)]
public ActionResult ViewStockNext(int firstItem)
{
    // Do some stuff
}

Con esto, no tiene que modificar su enrutamiento solo para manejar un nombre de parámetro diferente. La biblioteca también admite su aplicación varias veces para que pueda mapear varias ortografías de parámetros (útil cuando se refactoriza sin romper su interfaz pública).

Puede obtenerlo de Nuget y leer el artículo de Jeffrey Palermo aquí.

Matthew Nichols
fuente
7

public ActionResult ViewNextItem(int? id)hace que el identero sea un tipo anulable, sin necesidad de conversiones de cadena <-> int.

Oskar Duveborn
fuente
3

Con la función Asistente de etiquetas de ASP.NET Core:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>
Sasha Yakobchuk
fuente
Irónicamente, la respuesta más corta es la mejor (esta).
1

Hay otra forma de lograrlo (descrita con más detalles en el ejemplo de Pager de Stephen Walther

Básicamente, crea un enlace en la vista:

Html.ActionLink("Next page", "Index", routeData)

En routeData puede especificar pares de nombre / valor (por ejemplo, routeData ["página"] = 5), y en la función de índice del controlador, los parámetros correspondientes reciben el valor. Es decir,

public ViewResult Index(int? page)

tendrá la página pasada como 5. Tengo que admitir que es bastante inusual que la cadena ("página") se convierta automáticamente en una variable, pero así es como MVC funciona en otros idiomas también ...

Felix
fuente
0

La razón del tratamiento especial de "id" es que se agrega al mapeo de ruta predeterminado. Para cambiar esto, vaya a Global.asax.cs y encontrará la siguiente línea:

routes.MapRoute ("Default", "{controller}/{action}/{id}", 
                 new { controller = "Home", action = "Index", id = "" });

Cámbielo a:

routes.MapRoute ("Default", "{controller}/{action}", 
                 new { controller = "Home", action = "Index" });
Aristoteles
fuente
0

O puede intentar cambiar el tipo de parámetro a cadena y luego convertir la cadena a un número entero en el método. Soy nuevo en MVC, pero creo que necesita objetos que aceptan valores NULL en su lista de parámetros, ¿de qué otra manera indicará el controlador que no se proporcionó dicho parámetro? Entonces...

public ActionResult ViewNextItem(string id)...
RAL
fuente