Przekazywanie parametru z widoku do akcji.

0

Cześć!

Mój problem polega na przekazaniu w RouteValues danych z widoku do akcji. Sprawa wygląda tak, że muszę parsować enuma i wynik parsowania chciałbym przekazać sobie do akcji. Enuma mam zapisanego w TempData. Wobec tego, wyciągam sobie na początku widoku tego enuma z TempData i od razu parsuję na właściwy typ. Wygląda to standardowo:

    var typEnum = TempData["klucz"] as MyEnumType?;

W widoku mam tak tworzone hiperłącze na moim przycisku:

Url.Action("Akcja", "Kontroler", new{TypEnum = typEnum})

Debugowałem step-by-step i wynik parsowania jest prawidłowy, typEnum jest określony jako MyEnumType i ma wartość taką, jaką zapisywałem wcześniej w kontrolerze. Zapisywałem tak:

TempData["klucz"] = zapisywanyTypEnum;

Mimo zdawałoby się prawidłowych wyników parsowania do akcji za każdym razem leci null. Jeśli jednak na widoku określę typEnum tak:

var typEnum = MyEnumType.Etykieta1;

To wtedy do akcji jest przekazywane prawidłowo. Nie mam zielonego pojęcia dlaczego kiedy parsuję to wysyłany jest null, a kiedy podaję na sztywno to samo to wtedy jest dobrze.

Będę wdzięczny i z góry dziękuję za wszelkie wskazówki. Ja już dostaję spazmów, bo nie mam pojęcia co tu nie gra.

Pozdrawiam,
Dawid.

0

A gdyby po prostu przesłać stringa lub inta i parsnąć go w środku?

0

A jak przesyłasz z widoku do akcji? Bo to co pokazałeś, to przesłanie z akcji do widoku i to powinno działać prawidłowo.

0
WeiXiao napisał(a):

A gdyby po prostu przesłać stringa lub inta i parsnąć go w środku?

Co masz dokładnie na myśli? Chodzi Ci o pominięcie przekazywania enuma w parametrze i dobranie się do TempData na poziomie wywoływanej akcji czy przesłanie stringa jako parametru i parsowanie w akcji?

0
somekind napisał(a):

A jak przesyłasz z widoku do akcji? Bo to co pokazałeś, to przesłanie z akcji do widoku i to powinno działać prawidłowo.

Ja też nie do końca rozumiem. Mam akcję Akcja w kontrolerze Kontroler, sygnatura:

public ActionResult Akcja(MyEnumType typEnum)

Ten url:

Url.Action("Akcja", "Kontroler", new{TypEnum = typEnum})

jest przypisany do przycisku, który jest osadzony w tabeli.

0
dawid75_75 napisał(a):
somekind napisał(a):

A jak przesyłasz z widoku do akcji? Bo to co pokazałeś, to przesłanie z akcji do widoku i to powinno działać prawidłowo.

Ja też nie do końca rozumiem. Mam akcję Akcja w kontrolerze Kontroler, sygnatura:

public ActionResult Akcja(MyEnumType typEnum)

Ten url:

Url.Action("Akcja", "Kontroler", new{TypEnum = typEnum})

jest przypisany do przycisku, który jest osadzony w tabeli.

Ważne jest też (tak mi się wydaje) nazwa parametru w akcji. Domyślnie w routingu jest id. I daj też tak na akcję.

public ActionResult Akcja(MyEnumType id)
0

Id też przesyłam, ale z tym nie ma żadnego problemu. Sygnatura formalnie wygląda tak:

public ActionResult Akcja(int id, MyEnumType typEnum)

a urla generuję tak:

Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

I z przekazywaniem id nie ma żadnego problemu, zawsze jest prawidłowe. Dlatego pominąłem id w rozważaniach. Problem w tym, że jak zrobię na widoku tak:

@{
 var typEnum = TempData["klucz"] as MyEnumType?;
}
...
Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

to do akcji Akcja leci null pomimo tego, że w zmiennej jest prawidłowa wartość. Kidey robię dla przykładu tak:

@{
 var typEnum = MyEnumType.Etykieta1;
}
...
Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

to wtedy jest przekazywana prawidłowa wartość.
Nie mam pojęcia skąd takie zachowanie. Dodam, że przycisk, do którego zapisuję url'a jest na gridzie devexpressowym. Powtarzam też, że debugowanie krok po kroku pokazuje wyraźnie, że generowany jest prawidłowy url.

1

Stawiam na routing

0
dawid75_75 napisał(a):

Id też przesyłam, ale z tym nie ma żadnego problemu. Sygnatura formalnie wygląda tak:

public ActionResult Akcja(int id, MyEnumType typEnum)

a urla generuję tak:

Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

W akcji parametr ma nazwę typEnum, a przesyłasz o nazwie TypEnum ? spróbuj takie samie

Mając takie coś:

public enum Test
{
    A,
    B,
    C
}

public IActionResult Test(Test input)
{
    var type = input;
    Console.WriteLine(type.GetType());
    return View();
}
@Html.ActionLink("Nazwa", "Test", "Controller", new { input = Test.B }) 

Wynik: wyświetla test.Models.Test z wartością B

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = "A"})

Wynik: wyświetla test.Models.Test z wartością A

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = "1"})

Wynik: wyświetla test.Models.Test z wartością B

zatem działa - ale chyba tylko na .NET Corze? dziwne

0
WeiXiao napisał(a):
dawid75_75 napisał(a):

Id też przesyłam, ale z tym nie ma żadnego problemu. Sygnatura formalnie wygląda tak:

public ActionResult Akcja(int id, MyEnumType typEnum)

a urla generuję tak:

Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

W akcji parametr ma nazwę typEnum, a przesyłasz o nazwie TypEnum ? spróbuj takie samie

Tak samo nie działa. Poza tym, kiedy wyślę enuma wpisanego na sztywno to działa mimo różnicy wielkości znaków, tak więc bindowanie parametrów jest case insensitive.

0

Może dodaj sobie do routingu opcjonalny parametr po id o nazwie takiej jak w akcji

0
WeiXiao napisał(a):
dawid75_75 napisał(a):

Id też przesyłam, ale z tym nie ma żadnego problemu. Sygnatura formalnie wygląda tak:

public ActionResult Akcja(int id, MyEnumType typEnum)

a urla generuję tak:

Url.Action("Akcja", "Kontroler", new{Id = Model.id, TypEnum = typEnum})

W akcji parametr ma nazwę typEnum, a przesyłasz o nazwie TypEnum ? spróbuj takie samie

Mając takie coś:

public enum Test
{
    A,
    B,
    C
}

public IActionResult Test(Test input)
{
    var type = input;
    Console.WriteLine(type.GetType());
    return View();
}
@Html.ActionLink("Nazwa", "Test", "Controller", new { input = Test.B }) 

Wynik: wyświetla test.Models.Test z wartością B

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = "A"})

Wynik: wyświetla test.Models.Test z wartością A

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = "1"})

Wynik: wyświetla test.Models.Test z wartością B

zatem działa - ale chyba tylko na .NET Corze? dziwne

Już spieszę - u mnie również działa jeśli zrobię dokładnie tak jak napisałeś. Najwyraźniej binder sam sobie radzi z parsowaniem w takim przypadku. Jeśli mógłbym poprosić to sprawdź teraz taką rzecz - dodaj na początku widoku zmienną w taki sposób:

@{
var enumToSend = Test.B;
}

A następnie w linku podaj tak:

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = enumToSend }) 

W pierwszym przypadku działa prawidłowo, w drugim leci null.

0

test321.PNG

0

Ok, tak też u mnie jeszcze działa. Przy tym parsowaniu jest jakiś problem. Jakbyś był tak miły to sprawdź jeszcze taki wariant:

@{
    var enumToSend = TempData["klucz"] as Test? ?? default(Test);
    TempData.Keep("klucz");
}

i w linku:

@Html.ActionLink("Nazwa", "Test", "Controller", new { input = enumToSend }) 

Ten wariant cały czas maltretuję i tylko ten nie działa. Pozostałe powyższe działają prawidłowo.

1

@dawid75_75:

Chociaż tutaj chyba ViewData by wystarczyła :P

test123.PNG

test4.PNG

0

U Ciebie działa. U mnie nie. Pozostaje szukać błędu gdzieś u mnie. Dzięki za wytrwałą pomoc, przynajmniej wiem, że zamysł miałem prawidłowy :P
PS: Dodanie Route nad akcją nic nie zmieniło.

0
dawid75_75 napisał(a):

U Ciebie działa. U mnie nie. Pozostaje szukać błędu gdzieś u mnie. Dzięki za wytrwałą pomoc, przynajmniej wiem, że zamysł miałem prawidłowy :P
PS: Dodanie Route nad akcją nic nie zmieniło.

A próbujesz na .NET Corze czy zwykłym?

0

MVC 5.

0
dawid75_75 napisał(a):

MVC 5.

The parameters dictionary contains a null entry for parameter 'input' of non-nullable type 'WebApplication3.Models.Test' for method 'System.Web.Mvc.ActionResult About(WebApplication3.Models.Test)' in 'WebApplication3.Controllers.HomeController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Nazwa parametru: parameters

Mi też coś krzyczy w chyba najnowszym "zwykłym" MVC

No cóż, trzeba przejść na Cora, bo został on przepisany od nowa(iirc) i wydaje się być bardziej ogarnięty :P

0

Zrób w sygnaturze Test? żeby przyjął nulla i zobacz co przyjdzie :P

0
dawid75_75 napisał(a):

Zrób w sygnaturze Test? żeby przyjął nulla i zobacz co przyjdzie :P

null :(

1

U mnie działa taka wersja na MVC5
Pytanie czy nie działa Ci nawet za pierwszym razem czy za kolejnymi bo może nie przepisujesz ponownie wartości enuma do TempData w metodzie Akcja?

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            TempData["enumType"] = EnumType.B;
            return View();
        }

        public ActionResult Test(int Id, EnumType enumType)
        {
            var type = enumType;
            Console.WriteLine(type.GetType());
            
            return View("index");
        }
       
    }

widok

@{
    ViewBag.Title = "Home Page";
}

<h1>Test enum</h1>

@{ 
    
 var typEnum = TempData["enumType"] as WebAppTest.Models.EnumType?; 

}

<a href="@Url.Action("Test", "Home", new{Id = 1, EnumType = typEnum})">Test</a><br />

@Html.ActionLink("Test", "test", "home", new { Id = 1, EnumType = typEnum }, null) <br />
@Html.ActionLink("Test", "test", "home", new { Id = 1, EnumType = 1 }, null) <br />
@Html.ActionLink("Test", "test", "home", new { Id = 1, EnumType = "B" }, null) <br />

0

Sprawa wygląda tak, że wywołuję devexpressowego grida z metody Index, a potem są callbacki od tego grida (odświeżenie, przerzucenie strony itp). Jednak w widoku grida za każdym razem enum jest odczytywany z TempData, a zaraz za nim robię TempData.Kepp("klucz") więc dane powinny być trzymane w TempData. Powiem więcej, co właśnie zauważyłem - jeśli w Index() ustawię w TempData jakąś wartość to jest ona przypisana do przycisku na gridzie, ale wygląda to tak, że nie jest ona akutalizowana w callbacku. Problem z devexpressem?

0

No i to jest idealny przykład wątku, który powinien polecieć do kosza z powodem "Autor złośliwie i uporczywie nie chce pomocy". Ty myślisz, że tu jakąś powieść kryminalną piszesz, że tak dodajesz kolejne strzępki śladów oraz poszlak budując napięcie i każąc czytelnikom się wszystkiego domyślać?

dawid75_75 napisał(a):

Sprawa wygląda tak, że wywołuję devexpressowego grida z metody Index, a potem są callbacki od tego grida (odświeżenie, przerzucenie strony itp). Jednak w widoku grida za każdym razem enum jest odczytywany z TempData, a zaraz za nim robię TempData.Kepp("klucz") więc dane powinny być trzymane w TempData. Powiem więcej, co właśnie zauważyłem - jeśli w Index() ustawię w TempData jakąś wartość to jest ona przypisana do przycisku na gridzie, ale wygląda to tak, że nie jest ona akutalizowana w callbacku. Problem z devexpressem?

Może jednak tych requestów jest więcej niż byś się spodziewał, albo trafiają pod inny URL?
A może po prostu w ogóle lepiej nie używać TempData tylko zrobić to w zgodzie z MVC?
Trudno stwierdzić, bo nadal nie wiadomo na czym właściwie polega problem.

0

Celowo uprościłem zagadnienie, bo przed napisaniem wątku sprawdziłem, czy przekazywanie parametrów w ogóle działa. Mam tu na myśli przypadki podane przez WeiXiao. Nie działa tylko to z parsowaniem z TempData wobec czego uznałem, że background zagadnienia nie ma znaczenia. Możliwe, że się pomyliłem - przepraszam, jestem w trakcie nauki tego frameworka.

0

@dawid75_75: pokaż te akcje grida i jego partialview.

1 użytkowników online, w tym zalogowanych: 0, gości: 1