У меня есть контроллер с методом действия следующим образом:
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. Я пробовал добавить один без параметров, и он отлично работает, но, конечно, мне это не подходит.





Ваша маршрутизация должна быть настроена в соответствии с {controller}/{action}/{firstItem}. Если вы оставили маршрутизацию как {controller}/{action}/{id} по умолчанию в вашем файле global.asax.cs, вам нужно будет передать id.
routes.MapRoute(
"Inventory",
"Inventory/{action}/{firstItem}",
new { controller = "Inventory", action = "ListAll", firstItem = "" }
);
... или что-то близкое к этому.
Кроме того, было бы разумно добавить объект ограничений в MapRoute, например: new { firstItem = @"\d" }. Таким образом, Только примет, если параметр является любым числом. Вы можете изменить регулярное выражение по своему усмотрению и даже ограничить количество десятичных знаков, например: new { firstItem = @"\d{4}" } - теперь оно может состоять только из 4 чисел. Обновлено: пример полностью измененного MapRoute: jsfiddle.net/HJRgT
Чтобы перефразировать Ответ Джаррета Мейера, вам нужно изменить имя параметра на 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.
Кроме того, чтобы это сработало, вам необходимо убедиться, что вы вызвали routes.MapMvcAttributeRoutes(); в методе RegisterRoutes(RouteCollection) приложения (обычно в шаблоне App_Start \ RouteConfig.cs). По умолчанию его там может не быть.
Использование вспомогательной функции тегов ASP.NET Core:
<a asp-controller = "Home" asp-action = "SetLanguage" asp-route-yourparam1 = "@item.Value">@item.Text</a>
По иронии судьбы, самый короткий ответ - лучший (этот).
Или просто переименуйте firstItem в id