Artykuł

sxc.hu sxc.hu
lut 07 2014
0

Praktyczne wykorzystanie Child Actions w ASP.NET MVC

ASP.NET MVC to w moim odczuciu świetna platforma do budowy zarówno prostych jak i zaawansowanych web-aplikacji. W stosunku do Web Forms widać tutaj ogromny postęp. Twórcy tego rozwiązania postawili na sprawdzone schematy, biblioteki oraz zapewnili szerokie możliwości konfiguracji oraz rozbudowy naszych aplikacji. Nikogo już nie dziwią mechanizmy IoC, czy testy jednostkowe będące na porządku dziennym w świecie MVC.

Dla mnie osobiście szczególną rolę odgrywają nowe możliwości w aspekcie budowy layoutu. Mamy tutaj bowiem opcję tworzenia rozbudowanych widoków korzystających z engine Razor oraz opcję wykorzystania wspólnego szablonu dla wielu różnych stron. Oczywiście rozwiązanie typu Master template dziś już nikogo nie szokuje, ale mnie osobiście bardzo ucieszyły dodatkowo możliwości dostępne w ASP.NET MVC. Do gustu szczególnie przypadły mi tytułowe Child Actions, które świetnie funkcjonują w świecie platformy Microsoftu i w prosty sposób umożliwiają włączenie do layoutu określonego widoku aktywnie korzystającego z logiki biznesowej. Dziś mam właśnie zamiar przedstawić funkcjonowanie tego mechanizmu w praktyce.

Istota Child Actions

Tworząc witryny, praktycznie zawsze mamy pewne określone elementy, które cechują się tym, że występują na wszystkich (lub sporej grupie) podstronach. Często to są to teksty statyczne, ale w niektórych przypadkach mamy do czynienia z elementami dynamicznymi, które są pobierane z bazy danych, lub w jakikolwiek inny sposób pozyskiwane z modelu (dla przykładu, na blogu będzie to drzewo kategorii). I właśnie w tym miejscu pojawia się problem.

Rozpatrując ten przypadek z perspektywy ASP.NET MVC, wiemy o tym, że w danym momencie wywoływana jest dokładnie jedna akcja z konkretnego kontrolera. Zatem w jaki sposób zasilić nasze menu drzewem kategorii? Czy operację pobierania danych do menu powinniśmy umieścić w określonej metodzie, a następnie wywoływać w każdej możliwej akcji wykonywanej przez użytkownika naszej witryny?

Odpowiedź brzmi Nie. A właściwie to Nie, nie i jeszcze raz nie!. W ASP.NET MVC mamy na takie rzeczy dużo lepsze sposoby.

Lekiem na całe zło, jest właśnie tytułowy Child Actions. Istota tego mechanizmu jest bardzo prosta i zasadniczo sprowadza się do 4 kroków:

  1. Wewnątrz projektu tworzymy dodatkowy kontroler (lub wykorzystujemy jeden z istniejących)
  2. Dodajemy nową akcję do kontrolera, która zajmie się pobraniem danych z modelu
  3. Do akcji dodajemy PartialView, który wyświetli wcześniej pobrane dane
  4. W layoucie/wybranym widoku wywołujemy HtmlHelper.Action, w którym wskazujemy na wspominany wyżej kontroler oraz akcję
  5. Jak widać z powyższego akapitu, nie wygląda to wszystko na skomplikowany proces, a poniższe akapity ukażą, że jest to nawet łatwiejsze niż się Wam się w tej chwili wydaje.

    Child Actions w praktyce - przygotowujemy grunt

    Na wstępie zaznaczę, że w dalszej części tekstu będę korzystać z VS 2013 Express for Web oraz ASP.NET MVC w wersji 5.

    Pracę zaczynamy od utworzenia nowego projektu web aplikacji. Osobiście wybrałem wariant pustej aplikacji oraz zaznaczyłem pole wyboru MVC. Dzięki temu utworzony zostanie projekt o ramowej strukturze, który nie będzie zawierał zbędnych w tym przypadku elementów.

    W kolejnym kroku musicie dodać kontroler, który będzie Waszym głównym i którego zasadniczym zadaniem będzie po prostu wyświetlenie prostego widoku. Możecie go nazwać w dowolny sposób, ale załóżmy że w moim przykładzie będzie to HomeController.

    Visual Studio wspaniałomyślnie powinien dodać również metodę Index, która na nasze dzisiejsze potrzeby będzie wystarczająca w takiej postaci w jakiej jest:

    public ActionResult Index()
    {
        return View();
    }

    Kolejnym krokiem będzie dodanie widoku dla tej akcji. Najprościej to zrobić korzystając z opcji Add View, którą znajdziecie w menu kontekstowym wewnątrz metody Index. Pozostawiamy wszystkie opcje w ich domyślnej konfiguracji, by nie komplikować sobie zbytnio życia.

    W wyniku naszej akcji oprócz widoku dla akcji Index, wygenerowany zostanie również główny layout dla całej aplikacji, co również jest nam w tym przypadku na rękę. Ponieważ zawiera on kilka zbędnych elementów, poniżej przedstawiam odchudzoną wersję na nasze potrzeby:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - My ASP.NET Application</title>
    </head>
    <body>
        <header>
            <h1>Test application</h1>
        </header>
        <div id="menu">
            <!-- TODO add menu -->
        </div>
        <hr />
        @RenderBody()
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </body>
    </html>

    To na co warto zwrócić uwagę, to komentarz TODO. W następnych akapitach podmienimy jego zawartość konkretnym kawałkiem kodu.

    Wrócimy teraz do samego widoku. Zasadniczo to nie ma konieczności zmiany jego zawartości, aczkolwiek możecie dodać tam coś od siebie:

    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    <p>Hello World</p>

    Nasza web-aplikacja jest już w tej chwili gotowa do działania, o czym możecie się przekonać włączając tryb debugowania. W kolejnym kroku wykonamy już konkretne operacje związane z wprowadzeniem Child Actions.

    Child Actions w praktyce - konkretne działania

    Ok - skoro mamy już podwaliny aplikacji, przyszła najwyższa pora na konkretne działania. Przede wszystkim, zgodnie z tym co wcześniej napisałem, musimy wygenerować nową metodę w wybranym przez nas kontrolerze. Nie będę w tym przypadku komplikował sprawy i dodam akcję do kontrolera Home:

    public PartialViewResult Menu()
    {
        return PartialView(new List<string>()
        {
            "Index", "About", "Contact"
        });
    }

    W tym przypadku dodajemy akcję, która zwraca PartialView (widok częściowy). W ramach metody PartialView, zwracamy do widoku prostą kolekcję, zawierająca nazwy akcji, które mają się znaleźć w menu. Oczywiście w tej chwili te akcje są niezaimplementowane, ale możecie mi wierzyć (lub zaimplementować je sami), że ten mechanizm zadziała.

    W kolejnym kroku musimy stworzyć nowy widok. Najłatwiej jest to oczywiście zrobić za pomocą opcji Add View z menu kontekstowego tej akcji. W nowo otwartym oknie zaznaczamy opcję Create as a partial view oraz wprowadzamy nazwę Menu.

    Tym razem widok będzie kompletnie pusty, więc sami musimy dodać jego zawartość:

    @model IEnumerable<string>
    <ul>
        @foreach (string menuItem in @Model)
        {
        <li>@Html.ActionLink(menuItem, menuItem)</li>
        }
    </ul>

    Głównym i zarazem jedynym zadaniem tego widoku, jest wyświetlenie menu na podstawie wcześniej przygotowanej kolekcji stringów. Do wygenerowania linków wykorzystujemy HtmlHelper ActionLink. Tekst wyświetlany oraz nazwa akcji są takie same, ot tak po prostu dla wygody. Założyłem również, że w tym przypadku poruszamy się w obrębie jednego kontrolera. Oczywiście metoda ActionLink posiada znacznie większą liczbę kombinacji, które możemy zastosować.

    Zwieńczeniem naszych prac, będzie edycja pliku layoutu i zamiana wcześniej pozostawionego TODO na konkretny kod:

    @Html.Action("Menu")

    Również w tym przypadku metoda Action ma znacznie więcej dostępnych wywołań i nic nie stoi na przeszkodzie, by w ten sposób wyzwolić metodę zdefiniowaną w innym kontrolerze.

    Efektem naszych działań będzie brzydka, aczkolwiek działająca strona widoczna na poniższym screenie.

    Mam nadzieję, że zachęciłem Was do wykorzystania Child Actions, które w moim odczuciu w wymierny sposób ułatwiają tworzenie dynamicznych layoutów. Pamiętajcie również, że nowe akcje kontrolera nie muszą być umieszczone w już istniejącej konstrukcji. Jest to szczególnie ważne, gdy przy wywoływaniu kontrolera konieczne są jakieś dodatkowe parametry, lub mamy do czynienia z rozbudowanym łańcuchem zależności. W takiej sytuacji warto sobie stworzyć prosty kontroler na boku, który załatwi sprawę w najprostszy możliwy sposób.

    Gotowy projekt znajdziecie tutaj.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus