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

Будь-які ідеї, чому я отримав би цю помилку і що мені потрібно зробити, щоб її виправити?

Я спробував додати ще один метод, який бере ціле число до класу, він також не працює з тієї ж причини. Я спробував додати ту, яка займає рядок, і рядок встановлено на нуль. Я спробував додати його без параметрів, і це працює чудово, але, звичайно, він не відповідає моїм потребам.

Відповіді:


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"
Kyle Trauberman

8
Плюс світ доцільно додати об'єкт ТРУДНОЩІ до MapRoute, наприклад , так: new { firstItem = @"\d" }. Таким чином він буде прийнятий лише в тому випадку, якщо параметром є будь-який вид числа. Ви можете змінювати регулярний вираз, як хочете, і навіть обмежувати кількість десяткових знаків, як це: new { firstItem = @"\d{4}" }- тепер він може бути лише 4 числа. Редагувати: приклад повністю модифікованого MapRoute
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

Щоб перефразовувати відповідь Жаррет Мейєра , вам потрібно змінити ім'я параметра на '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ціле число нульовим типом, не потрібно перетворення рядка <-> int.


3

Використання функції ASP.NET Core Tag Helper:

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

Як не дивно, найкраща відповідь - найкраща (ця).

1

Є ще один спосіб досягти цього (детальніше описаний у прикладі пейджера Стівена Уолтера

По суті, ви створюєте посилання у представленні:

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

У routeData можна вказати пари імен / значень пар (наприклад, routeData ["сторінка"] = 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)...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.