ASP.NET MVC - przekazanie parametrów do kontrolera

105

Mam kontroler z następującą metodą akcji:

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

A kiedy go uruchamiam, pojawia się błąd o treści:

Słownik parametrów nie zawiera prawidłowej wartości typu „System.Int32” dla parametru „firstItem”. Aby parametr był opcjonalny, jego typ powinien być typem referencyjnym lub typem dopuszczającym wartość Nullable.

W pewnym momencie miałem to działające i postanowiłem wypróbować funkcję bez parametrów. Stwierdziwszy, że kontroler nie był trwały, wstawiłem parametr z powrotem, teraz odmawia on rozpoznania parametru przy wywołaniu metody.

Używam tej składni adresu URL, aby wywołać akcję:

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

Jakieś pomysły, dlaczego otrzymuję ten błąd i co muszę zrobić, aby go naprawić?

Próbowałem dodać inną metodę, która przyjmuje liczbę całkowitą do klasy, ale również zawodzi z tego samego powodu. Próbowałem dodać taki, który przyjmuje ciąg, a ciąg jest ustawiony na null. Próbowałem dodać jeden bez parametrów i działa dobrze, ale oczywiście nie będzie pasował do moich potrzeb.

Dziwny
źródło

Odpowiedzi:

106

Twój routing musi być skonfigurowany zgodnie z liniami {controller}/{action}/{firstItem}. Jeśli pozostawiłeś routing jako domyślny {controller}/{action}/{id}w swoim global.asax.cspliku, będziesz musiał przekazać id.

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

... lub coś podobnego.

Jarrett Meyer
źródło
44
Lub po prostu zmień nazwę „firstItem” na „id”
Kyle Trauberman
8
Plus to świat być mądry, aby dodać obiekt do MapRoute ograniczeń, tak jak poniżej: new { firstItem = @"\d" }. W ten sposób będzie akceptować tylko wtedy, gdy parametr jest jakąkolwiek liczbą. Możesz modyfikować wyrażenie regularne, jak chcesz, a nawet ograniczyć liczbę miejsc po przecinku, na przykład: new { firstItem = @"\d{4}" }- teraz może mieć tylko 4 cyfry. Edycja: przykład w pełni zmodyfikowanej MapRoute
KristianB
86

możesz zmienić firstItem na id i będzie działać

możesz zmienić routing na global.asax (nie polecam tego)

i nie mogę uwierzyć, że nikt o tym nie wspomniał, możesz zadzwonić:

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

W przypadku @ Url.Akcja byłaby:

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

w zależności od tego, co robisz, to ostatnie będzie bardziej odpowiednie. Powinieneś także rozważyć nie wykonywanie akcji ViewStockNext, a zamiast tego akcję ViewStock z indeksem. (moje 2 centy)

Bart Calixto
źródło
15

Aby przeformułować odpowiedź Jarreta Meyera , musisz zmienić nazwę parametru na „id” lub dodać taką trasę:

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

Powodem jest to, że trasa domyślna wyszukuje tylko akcje bez parametru lub parametru o nazwie „id”.

Edycja: heh, nieważne Jarret dodał przykład trasy po wysłaniu.

Matt Mitchell
źródło
8

lub zrób to z atrybutem trasy:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}
Yar
źródło
Ta właściwość może nie działać ze starszymi wersjami MVC.
dr Suat Atan
Ponadto, aby to zadziałało, musisz upewnić się, że wywołałeś routes.MapMvcAttributeRoutes();w ramach RegisterRoutes(RouteCollection)metody aplikacji (zwykle szkieletowej w App_Start \ RouteConfig.cs). Domyślnie może tam nie być.
Daniel Scott,
7

Firma Headspring stworzyła ładną bibliotekę, która umożliwia dodawanie aliasów do parametrów w atrybutach akcji. Wygląda to tak:

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

Dzięki temu nie musisz zmieniać routingu tylko po to, aby obsłużyć inną nazwę parametru. Biblioteka obsługuje również wielokrotne jej stosowanie, dzięki czemu można mapować pisownię kilku parametrów (przydatne podczas refaktoryzacji bez przerywania publicznego interfejsu).

Możesz go zdobyć od Nuget i przeczytać artykuł Jeffreya Palermo na ten temat tutaj

Matthew Nichols
źródło
7

public ActionResult ViewNextItem(int? id)sprawia, że idliczba całkowita jest typem dopuszczającym wartość null, nie ma potrzeby konwersji ciągu <-> int.

Oskar Duveborn
źródło
3

Korzystanie z funkcji pomocnika tagów ASP.NET Core:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>
Sasha Yakobchuk
źródło
Jak na ironię, najkrótsza odpowiedź jest najlepsza (ta).
1

Jest na to inny sposób (opisany bardziej szczegółowo w przykładzie Stephena Walthera na Pager

Zasadniczo tworzysz łącze w widoku:

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

W routeData można określić pary nazwa / wartość (np. RouteData ["strona"] = 5), aw funkcji indeksu kontrolera odpowiednie parametry otrzymują wartość. To jest,

public ViewResult Index(int? page)

strona zostanie przekazana jako 5. Muszę przyznać, że to dość niezwykłe, że ciąg ("strona") automagicznie staje się zmienną - ale tak właśnie działa MVC w innych językach ...

Felix
źródło
0

Powodem specjalnego traktowania „id” jest to, że jest dodawany do domyślnego mapowania trasy. Aby to zmienić, przejdź do Global.asax.cs, a znajdziesz następujący wiersz:

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

Zmień to na:

routes.MapRoute ("Default", "{controller}/{action}", 
                 new { controller = "Home", action = "Index" });
Arystoteles
źródło
0

Możesz też spróbować zmienić typ parametru na łańcuch, a następnie przekonwertować ciąg na liczbę całkowitą w metodzie. Jestem nowy w MVC, ale uważam, że na liście parametrów potrzebne są obiekty dopuszczające wartość null, w jaki inny sposób kontroler wskaże, że nie podano takiego parametru? Więc...

public ActionResult ViewNextItem(string id)...
RAL
źródło