ASP.NET MVC - transmission de paramètres au contrôleur

105

J'ai un contrôleur avec une méthode d'action comme suit:

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

Et quand je l'exécute, j'obtiens une erreur indiquant:

Le dictionnaire de paramètres ne contient pas de valeur valide de type «System.Int32» pour le paramètre «firstItem». Pour rendre un paramètre facultatif, son type doit être soit un type référence, soit un type Nullable.

Je l'ai fait fonctionner à un moment donné et j'ai décidé d'essayer la fonction sans paramètres. En découvrant que le contrôleur n'était pas persistant, j'ai remis le paramètre, maintenant il refuse de reconnaître le paramètre lorsque j'appelle la méthode.

J'utilise cette syntaxe d'URL pour appeler l'action:

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

Des idées pour lesquelles j'obtiendrais cette erreur et ce que je dois faire pour la corriger?

J'ai essayé d'ajouter une autre méthode qui prend un entier à la classe, elle échoue également avec la même raison. J'ai essayé d'en ajouter un qui prend une chaîne et la chaîne est définie sur null. J'ai essayé d'en ajouter un sans paramètres et cela fonctionne bien, mais bien sûr, cela ne répondra pas à mes besoins.

Impair
la source

Réponses:

106

Votre routage doit être configuré sur le modèle de {controller}/{action}/{firstItem}. Si vous avez laissé le routage par défaut {controller}/{action}/{id}dans votre global.asax.csfichier, vous devrez le transmettre id.

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

... Ou quelque chose proche de cela.

Jarrett Meyer
la source
44
Ou simplement renommer "firstItem" en "id"
Kyle Trauberman
8
De plus , il monde sage d'ajouter un objet de contraintes à l'MapRoute, comme suit: new { firstItem = @"\d" }. De cette façon, il n'acceptera que si le paramètre est n'importe quel type de nombre. Vous pouvez modifier l'expression rationnelle à votre guise, et même limiter le nombre de décimales, comme ceci: new { firstItem = @"\d{4}" }- maintenant, elle ne peut comporter que 4 nombres. Edit: exemple de MapRoute entièrement modifié: jsfiddle.net/HJRgT
KristianB
86

vous pouvez changer firstItem en id et cela fonctionnera

vous pouvez changer le routage sur global.asax (je ne le recommande pas)

et, je ne peux pas croire que personne n'ait mentionné cela, vous pouvez appeler:

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

Dans une @ Url.Action serait:

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

selon le type de ce que vous faites, le dernier sera plus adapté. Vous devez également envisager de ne pas effectuer l'action ViewStockNext et plutôt une action ViewStock avec index. (mes 2 cents)

Bart Calixto
la source
15

Pour reformuler la réponse de Jarret Meyer , vous devez changer le nom du paramètre en 'id' ou ajouter une route comme celle-ci:

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

La raison en est que la route par défaut ne recherche que les actions sans paramètre ou avec un paramètre appelé «id».

Edit: Heh, Nevermind Jarret a ajouté un exemple d'itinéraire après la publication.

Matt Mitchell
la source
8

ou faites-le avec Attribut d'itinéraire:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}
Yar
la source
Cette propriété peut ne pas fonctionner avec les anciennes versions de MVC.
Suat Atan PhD
En outre, pour que cela fonctionne, vous devez vous assurer que vous avez appelé routes.MapMvcAttributeRoutes();dans la RegisterRoutes(RouteCollection)méthode de l'application (généralement scaffolded dans App_Start \ RouteConfig.cs). Ce n'est peut-être pas là par défaut.
Daniel Scott
7

Headspring a créé une belle bibliothèque qui vous permet d'ajouter des alias à vos paramètres dans les attributs de l'action. Cela ressemble à ceci:

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

Avec cela, vous n'avez pas à modifier votre routage juste pour gérer un nom de paramètre différent. La bibliothèque prend également en charge son application plusieurs fois afin que vous puissiez mapper plusieurs orthographes de paramètres (pratique lors de la refactorisation sans casser votre interface publique).

Vous pouvez l'obtenir auprès de Nuget et lire l'article de Jeffrey Palermo à ce sujet ici

Matthew Nichols
la source
7

public ActionResult ViewNextItem(int? id)fait de l' identier un type Nullable, pas besoin de conversions de chaîne <-> int.

Oskar Duveborn
la source
3

À l'aide de la fonctionnalité d'assistance de balise ASP.NET Core:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>
Sasha Yakobchuk
la source
Ironiquement, la réponse la plus courte est la meilleure (celle-ci).
1

Il existe une autre façon d'accomplir cela (décrite plus en détail dans Stephen Walther exemple Pager de

Essentiellement, vous créez un lien dans la vue:

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

Dans routeData, vous pouvez spécifier des paires nom / valeur (par exemple, routeData ["page"] = 5), et dans la fonction d'index du contrôleur, les paramètres correspondants reçoivent la valeur. C'est,

public ViewResult Index(int? page)

aura la page passée à 5. Je dois admettre qu'il est assez inhabituel que la chaîne ("page") devienne automatiquement une variable - mais c'est ainsi que MVC fonctionne également dans d'autres langues ...

Félix
la source
0

La raison du traitement spécial de «id» est qu'il est ajouté au mappage d'itinéraire par défaut. Pour changer cela, allez dans Global.asax.cs, et vous trouverez la ligne suivante:

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

Changez-le en:

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

Ou, vous pouvez essayer de changer le type de paramètre en chaîne, puis convertir la chaîne en entier dans la méthode. Je suis nouveau dans MVC, mais je pense que vous avez besoin d'objets Nullable dans votre liste de paramètres, comment le contrôleur indiquera-t-il qu'un tel paramètre n'a pas été fourni? Alors...

public ActionResult ViewNextItem(string id)...
RAL
la source