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

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

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

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

The parameters dictionary does not contain a valid value of type 'System.Int32' for parameter 'firstItem'. To make a parameter optional its type should either be a reference type or a Nullable type.

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

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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
106
0
357 966
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Ответ принят как подходящий

Ваша маршрутизация должна быть настроена в соответствии с {controller}/{action}/{firstItem}. Если вы оставили маршрутизацию как {controller}/{action}/{id} по умолчанию в вашем файле global.asax.cs, вам нужно будет передать id.

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

... или что-то близкое к этому.

Или просто переименуйте firstItem в id

Kyle Trauberman 06.02.2009 19:01

Кроме того, было бы разумно добавить объект ограничений в MapRoute, например: new { firstItem = @"\d" }. Таким образом, Только примет, если параметр является любым числом. Вы можете изменить регулярное выражение по своему усмотрению и даже ограничить количество десятичных знаков, например: new { firstItem = @"\d{4}" } - теперь оно может состоять только из 4 чисел. Обновлено: пример полностью измененного MapRoute: jsfiddle.net/HJRgT

KristianB 18.09.2011 20:57

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

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

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

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

Или вы можете попробовать изменить тип параметра на строку, а затем преобразовать строку в целое число в методе. Я новичок в MVC, но считаю, что вам нужны объекты, допускающие значение NULL, в вашем списке параметров, как еще контроллер укажет, что такой параметр не был предоставлен? Так...

public ActionResult ViewNextItem(string id)...

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

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

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

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

В routeData вы можете указать пары имя / значение (например, routeData ["page"] = 5), а в функции Index контроллера соответствующие параметры получают значение. То есть,

public ViewResult Index(int? page)

страница будет передано как 5. Я должен признать, что довольно необычно, что строка ("страница") автоматически становится переменной - но так MVC работает и на других языках ...

вы можете изменить firstItem на id, и он будет работать

вы можете изменить маршрутизацию на global.asax (я не рекомендую это)

и, не могу поверить, что никто об этом не упомянул, вы можете вызвать:

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

В @ Url.Action будет выглядеть так:

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

в зависимости от того, чем вы занимаетесь, последний будет более подходящим. Также вам следует подумать о том, чтобы не выполнять действие ViewStockNext, а вместо этого выполнять действие ViewStock с index. (мои 2 цента)

Причина особого обращения с «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" });

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

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

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

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

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

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

Это свойство может не работать со старыми версиями MVC.

Suat Atan PhD 01.06.2017 17:05

Кроме того, чтобы это сработало, вам необходимо убедиться, что вы вызвали routes.MapMvcAttributeRoutes(); в методе RegisterRoutes(RouteCollection) приложения (обычно в шаблоне App_Start \ RouteConfig.cs). По умолчанию его там может не быть.

Daniel Scott 15.12.2019 01:04

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

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

По иронии судьбы, самый короткий ответ - лучший (этот).

user6911980 06.06.2019 23:24

Другие вопросы по теме