ASP.NET MVC-将参数传递给控制器


105

我有一个具有操作方法的控制器,如下所示:

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

当我运行它时,我得到一个错误说明:

参数字典对于参数“ firstItem”不包含类型为“ System.Int32”的有效值。要使参数成为可选参数,其类型应为引用类型或Nullable类型。

我曾经在某一点上工作过,所以我决定尝试不带参数的功能。发现控制器不是持久性的,我将参数放回去,现在当我调用方法时它拒绝识别参数。

我正在使用以下url语法来调用操作:

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

有什么主意为什么会出现这个错误以及我需要做什么来解决它?

我试图添加另一个方法,该方法将一个整数添加到类中,但由于同样的原因它也会失败。我尝试添加一个需要一个字符串的字符串,并且该字符串设置为null。我尝试添加一个不带参数的方法,效果很好,但是当然不适合我的需求。

Answers:


106

您需要按照设置路线{controller}/{action}/{firstItem}。如果您{controller}/{action}/{id}global.asax.cs文件中将路由保留为默认设置,则需要传递id

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

...或类似的东西。


44
或只是将“ firstItem”重命名为“ id”
凯尔·特劳伯曼

8
另外,明智的做法是向MapRoute添加一个约束对象,如下所示:new { firstItem = @"\d" }。这样,它在参数为任何数字时才接受。您可以根据需要修改正则表达式,甚至可以限制小数位数,如下所示:new { firstItem = @"\d{4}" }-现在只能为4个数字。编辑:完全修改的MapRoute的示例:jsfiddle.net/HJRgT
KristianB

86

您可以将firstItem更改为id,它将起作用

您可以更改global.asax上的路由(我不建议这样做)

而且,不敢相信没有人提到这一点,您可以致电:

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

在@ Url.Action中将是:

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

根据您的工作类型,最后一个会更适合。另外,您应该考虑不执行ViewStockNext操作,而是执行带索引的ViewStock操作。(我的2美分)


15

要改写Jarret Meyer的答案,您需要将参数名称更改为'id'或添加如下所示的路由:

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

原因是默认路由仅查找没有参数或名为“ id”的参数的操作。

编辑:嘿,没关系Jarret发布后添加了一个路线示例。


8

或使用Route Attribute:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}

此属性可能不适用于较早的MVC版本。
Suat Atan PhD

另外,要使此方法起作用,您需要确保已routes.MapMvcAttributeRoutes();在应用程序的RegisterRoutes(RouteCollection)方法内调用(通常是脚手架到App_Start \ RouteConfig.cs中)。默认情况下它可能不在其中。
丹尼尔·斯科特

7

Headspring创建了一个不错的库,允许您在操作的属性中为参数添加别名。看起来像这样:

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

这样,您不必更改路由就可以处理不同的参数名称。该库还支持多次应用它,因此您可以映射多个参数拼写(在重构时非常方便,而不会破坏您的公共接口)。

您可以从Nuget获取它,并在此处阅读Jeffrey Palermo的文章。



3

使用ASP.NET Core标记帮助器功能:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>

具有讽刺意味的是,最短的答案是最好的(此答案)。

1

还有另一种方法可以做到这一点(在Stephen Walther的Pager示例中有更详细的描述

本质上,您可以在视图中创建一个链接:

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

在routeData中,可以指定名称/值对(例如,routeData [“ page”] = 5),并且在控制器的Index函数中,相应的参数将接收该值。那是,

public ViewResult Index(int? page)

将会以5传递页面。我必须承认,字符串(“页面”)自动变成变量是很不寻常的-但这也是MVC在其他语言中的工作方式...


0

对“ id”进行特殊处理的原因是将其添加到默认路由映射中。要更改此设置,请转到Global.asax.cs,您将找到以下行:

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

更改为:

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

0

或者,您可以尝试将参数类型更改为字符串,然后在方法中将字符串转换为整数。我是MVC的新手,但我相信您需要在参数列表中添加可为空的对象,否则控制器将如何指示未提供此类参数?所以...

public ActionResult ViewNextItem(string id)...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.