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

我有一个操作方法如下的控制器:

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

当我运行它的时候,我得到一个错误:

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

我让它工作在一个点,我决定尝试没有参数的函数。发现控制器不是持久的,我把参数放回去,现在它拒绝识别参数时,我调用的方法。

我使用这个 url 语法来调用这个操作:

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

知道为什么我会得到这个错误,以及我需要做什么来修复它吗?

我已经尝试添加另一个方法,采取一个整数的类,它也失败了同样的原因。我试过添加一个接受字符串的值,这个字符串被设置为 null。我试过添加一个没有参数的,这个工作很好,但当然它不会适合我的需要。

398557 次浏览

Your routing needs to be set up along the lines of {controller}/{action}/{firstItem}. If you left the routing as the default {controller}/{action}/{id} in your global.asax.cs file, then you will need to pass in id.

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

... or something close to that.

To rephrase Jarret Meyer's answer, you need to change the parameter name to 'id' or add a route like this:

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

The reason is the default route only looks for actions with no parameter or a parameter called 'id'.

Edit: Heh, nevermind Jarret added a route example after posting.

Or, you could try changing the parameter type to string, then convert the string to an integer in the method. I am new to MVC, but I believe you need nullable objects in your parameter list, how else will the controller indicate that no such parameter was provided? So...

public ActionResult ViewNextItem(string id)...

public ActionResult ViewNextItem(int? id) makes the id integer a nullable type, no need for string<->int conversions.

There is another way to accomplish that (described in more details in Stephen Walther's Pager example

Essentially, you create a link in the view:

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

In routeData you can specify name/value pairs (e.g., routeData["page"] = 5), and in the controller Index function corresponding parameters receive the value. That is,

public ViewResult Index(int? page)

will have page passed as 5. I have to admit, it's quite unusual that string ("page") automagically becomes a variable - but that's how MVC works in other languages as well...

you can change firstItem to id and it will work

you can change the routing on global.asax (i do not recommed that)

and, can't believe no one mentioned this, you can call :

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

In a @Url.Action would be :

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

depending on the type of what you are doing, the last will be more suitable. Also you should consider not doing ViewStockNext action and instead a ViewStock action with index. (my 2cents)

The reason for the special treatment of "id" is that it is added to the default route mapping. To change this, go to Global.asax.cs, and you will find the following line:

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

Change it to:

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

Headspring created a nice library that allows you to add aliases to your parameters in attributes on the action. This looks like this:

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

With this you don't have to alter your routing just to handle a different parameter name. The library also supports applying it multiple times so you can map several parameter spellings (handy when refactoring without breaking your public interface).

You can get it from Nuget and read Jeffrey Palermo's article on it here

or do it with Route Attribute:

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

Using the ASP.NET Core Tag Helper feature:

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