ASP.NET MVC - передача параметров контроллеру

105

У меня есть контроллер с методом действия следующим образом:

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

И когда я запускаю его, я получаю сообщение об ошибке:

Словарь параметров не содержит допустимого значения типа System.Int32 для параметра firstItem. Чтобы сделать параметр необязательным, его тип должен быть либо ссылочным, либо Nullable.

Однажды у меня это работало, и я решил попробовать функцию без параметров. Обнаружив, что контроллер не был постоянным, я вернул параметр, теперь он отказывается распознавать параметр, когда я вызываю метод.

Я использую этот синтаксис URL для вызова действия:

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

Есть идеи, почему я получаю эту ошибку и что мне нужно сделать, чтобы ее исправить?

Я попытался добавить еще один метод, который принимает целое число в класс, но он также не работает по той же причине. Я пробовал добавить тот, который принимает строку, и для строки установлено значение null. Я пробовал добавить один без параметров, и он отлично работает, но, конечно, мне не подходит.

Странный
источник

Ответы:

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 с index. (мои 2 цента)

Барт Каликсто
источник
15

Чтобы перефразировать ответ Джаррета Мейера , вам нужно изменить имя параметра на id или добавить такой маршрут:

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

Причина в том, что маршрут по умолчанию ищет только действия без параметра или параметр с именем 'id'.

Изменить: Хех, неважно, что Джаррет добавил пример маршрута после публикации.

Мэтт Митчелл
источник
8

или сделайте это с помощью атрибута маршрута:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}
Яр
источник
Это свойство может не работать со старыми версиями MVC.
Суат Атан, доктор философии,
Кроме того, чтобы это работало, вам необходимо убедиться, что вы вызвали вызов routes.MapMvcAttributeRoutes();в RegisterRoutes(RouteCollection)методе приложения (обычно в шаблоне App_Start \ RouteConfig.cs). По умолчанию его может не быть.
Дэниел Скотт
7

Headspring создал прекрасную библиотеку, которая позволяет добавлять псевдонимы к вашим параметрам в атрибутах действия. Это выглядит так:

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

При этом вам не нужно изменять маршрутизацию только для обработки другого имени параметра. Библиотека также поддерживает его многократное применение, поэтому вы можете сопоставить несколько вариантов написания параметров (удобно при рефакторинге без нарушения общедоступного интерфейса).

Вы можете получить его у Nuget и прочитать статью Джеффри Палермо об этом здесь.

Мэтью Николс
источник
7

public ActionResult ViewNextItem(int? id)делает idцелое число типом, допускающим значение NULL, нет необходимости в преобразованиях string <-> int.

Оскар Дювеборн
источник
3

Использование вспомогательной функции тегов ASP.NET Core:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>
Саша Якобчук
источник
По иронии судьбы, самый короткий ответ - лучший (этот).
1

Есть еще один способ добиться этого (более подробно описанный в примере Стивена Вальтера с пейджером.

По сути, вы создаете ссылку в представлении:

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, но считаю, что вам нужны объекты, допускающие значение NULL, в вашем списке параметров, как еще контроллер укажет, что такой параметр не был предоставлен? Так...

public ActionResult ViewNextItem(string id)...
RAL
источник