Dzisiaj kolejny wpis o podstawach ASP.NET MVC. Tym razem chciałbym pokazać czym różnią się metody RenderBody, RenderSection, RenderPage oraz RenderPartial.
Zacznijmy od najbardziej znanej metody, RenderBody. Korzystamy z niej w przypadku zdefiniowanego Layout’u. Tworząc nowy, domyślny projekt automatycznie zostanie dodany w folderze shared plik _Layout.cshtml. Definiuje on domyślny szablon czyli zwartość, która jest powtarzana na każdej podstronie. Zamiast duplikować cześć wspólną (menu, stopka itp.) na każdej podstronie, możemy ją zdefiniować tylko raz w layout’cie. Przykład:
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script> </head> <body> <div class="page"> <div id="header"> <div id="title"> <h1>My MVC Application</h1> </div> <div id="logindisplay"> @Html.Partial("_LogOnPartial") </div> <div id="menucontainer"> <ul id="menu"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> </ul> </div> </div> <div id="main"> @RenderBody() </div> <div id="footer"> </div> </div> </body> </html>
Metoda RenderBody służy do wstrzyknięcia konkretnej treści. Layout definiuje cześć wspólną, ale potem w podstronach chcemy wstawić konkretną treść. W miejsce RenderBody, zostanie zatem umieszczona konkretna treść, specyficzna dla danej strony. Następnie aby skorzystać z layoutu, należy na podstronie albo w pliku ViewStart umieścić następujący kod:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Teraz widoki powinny definiować wyłącznie treść specyficzną dla danej strony, która zostanie wstrzyknięta w miejsce RenderBody.
RenderPage ma dość podobne zastosowanie. Służy do wyrenderowania konkretnej strony. Jako parametr przekazujemy nazwę strony, którą chcemy wygenerować oraz opcjonalnie parametry wejściowe.
Stwórzmy zatem jakiś widok w folderze Shared:
@{ ViewBag.Title = "SamplePage"; } <h2>SamplePage</h2> Jakas tresc
Następnie na dowolnej podstronie wyrenderujmy SamplePage:
@{ ViewBag.Title = "About"; } <h2>About</h2> @RenderPage("~/Views/Shared/SamplePage.cshtml")
Finalna treść będzie stanowić połączenie szablonu (layout), strony about oraz wyrenderowanej w niej SamplePage.cshtml. Nic nie szkodzi na przeszkodzie, aby wywołać kilka razy RenderPage na tej samej stronie. Po prostu, gdy mamy treść powtarzającą się na kilku stronach, możemy skorzystać z RenderPage.
Przekazanie parametru do RenderPage jest bardzo łatwe:
@RenderPage("~/Views/Shared/SamplePage.cshtml",new{Par1="Test"});
Następnie (SamplePage.cshtml):
@{ ViewBag.Title = "SamplePage"; } <h2>SamplePage</h2> Jakas tresc @Page.Par1
Alternatywnie można skorzystać z @PageData["Par1"]. Oczywiście w praktyce przekazuje się dane z Modelu, a nie ręcznie zdefiniowane w html.
Kolejna metoda, RenderSection jest znów ściśle powiązana z szablonem (_Layout). Ponadto, możemy definiować dowolną ilość sekcji:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>@ViewBag.Title - My ASP.NET MVC Application</title> <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" /> <meta name="viewport" content="width=device-width" /> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <h1>Glowna tresc</h1> @RenderBody(); <h2>Sekcja I</h2> @RenderSection("Section1",required:false); <h2>Sekcja II</h2> @RenderSection("Section2",required:false); </body> </html>
Pierwszy parametr metody to nazwa sekcji, drugi z kolei to flaga oznaczająca czy sekcja zawsze musi zostać użyta. Następnie na dowolnej podstronie możemy wstawić treść w poszczególne sekcje:
@{ ViewBag.Title = "About"; } <h2>About</h2> Glowna tresc @section Section1 { Jakas tresc dla sekcji I }
Jeśli ustawimy, że sekcja jest wymagana a nie wypełnimy ją treścią wtedy wystąpi błąd podczas generowania strony:
Section not defined: "Section2".
Na zakończenie warto również przyjrzeć się RenderPartial. Metoda, analogicznie jak RenderPage służy do wyrenderowania strony, przekazanej jako parametr wejściowy. Różnica polega na tym, że w przypadku RenderPartial podajemy po prostu nazwę widoku, a nie pełną ścieżkę:
@{ ViewBag.Title = "About"; } <h2>About</h2> Glowna tresc @{ Html.RenderPartial("SamplePage"); } @RenderPage("~/Views/Shared/SamplePage.cshtml")
Efekt docelowy jest ten sam – mechanizm za to jest trochę inny, szczególnie w przypadku wyszukiwania. RenderPartial podajemy tylko nazwę, zatem widok może znajdować się w Shared lub w folderze dedykowanym dla danego kontrolera.