Razor – nowy silnik renderujący w ASP.NET MVC 3.0 ![Udostępnij na: Facebook](images/ "Udostępnij na: Facebook")

Autor: Piotr Zieliński

Opublikowano: 2011-03-30

Wprowadzenie

Wersja 3.0 dostarcza nowy silnik renderujący, który znacząco upraszcza projektowanie widoków. W poprzednich wersjach do dyspozycji był wyłącznie aspx o dość niewygodnej składni. Razor posiada prostszą składnię, która wymaga po prostu mniejszej ilości kodu do uzyskania takich samych efektów co aspx. ASP.NET MVC daje pełną swobodę i można wykorzystywać w swoich projektach zarówno ASPX, jak i Razor. Istnieje również kilka innych silników, takich jak SPARK czy NHaml.

Podstawowa składnia Razor

Wyświetlanie zmiennych

Rozważmy wyświetlenie tekstu z modelu oraz daty za pomocą ASPX:

<h1>
        Witaj <%=ViewBag.Name %>! Aktualna data to <%=DateTime.Now %>
</h1>

W ASPX należy zamykać tagi znakami %>. Jest to dość kłopotliwe, zwłaszcza gdy trzeba wpisywać znak procenta (%), który znajduje się w mało wygodnej części klawiatury.

W przypadku Razor kod uprości się do:

<h1>
        Witaj @ViewBag.Name ! Aktualna data to @DateTime.Now 
</h1>

W Razor wystarczy przed zmienną umieścić znak @ – nie trzeba zamykać, tak jak w przypadku ASPX tagu. Jak widać, za pomocą tylko jednego znaku byliśmy w stanie wyświetlić zawartość zmiennej.

Pętle z zagnieżdżonym kodem HTML

W przypadku pętli przewaga Razor jest jeszcze bardziej widoczna (w ASPX niewygodne jest zamykanie nawiasów):

<%foreach(var item in Model){ %>
    <p><%=item %></p>
<%} %>

W Razor kod bardziej przypomina czysty C#, ponieważ nie trzeba definiować tagów za pomocą <%>:

@foreach (var item in Model)
{ 
    <p>@item</p>
}

Instrukcje sterujące IF

Przewagę Razor widać również na przykładzie instrukcji if (w przypadku ASPX prosty warunek wyglądał dość skomplikowanie):

<%if (Model.Length == 0)
    { %>
          <p>Brak towaru</p>
  <%}
       else
 { %>
          <p>Towar dostepny</p>
  <%} %>

W Razor wygląda to znacznie prościej:

@if (Model.Length == 0)
 {
    <p>Brak towaru</p>
}
 else
 {
    <p>Towar dostepny</p>
}

Kod pomiędzy klamrami musi być umieszczony w tagu HTML – w naszym przykładzie jest to <p>. Nie możemy bezpośrednio umieszczać tekstu pomiędzy klamrami. W przypadku gdy nie chcemy użyć żadnego formatowania HTML (takiego jak np. <p>), możemy wykorzystać element text:

@if(Model.Length!=0)
{
   <text>
   Jakis tekst
   </text>
}

Text stanowi specjalny element i nie zostanie on wygenerowany w docelowej stronie HTML (strona będzie zawierała wyłącznie zawartość elementu <text></text>).

Sekcje kodu

Jeśli potrzebujemy wykonać kod składający się z kilku linii, należy go umieścić w sekcji @{ }:

@{
   string text="Hello";
   text+=" World";
}
@text

Warto jednak pamiętać o podstawowej zasadzie MVC, która mówi, że widok powinien wyświetlać dane, a nie je generować. Powyższa sekcja jest analogiczna do <% %>, znanej z ASPX.

Wyświetlanie konkatenacji

Razor dysponuje również odpowiednikiem sekcji<%= %> (ASPX). Jeśli chcemy wyświetlić złączenie zmiennych, korzystamy z @( ):

@("Witaj " + ViewBag.Name)

Zawartość ze znakiem @

Jak już zapewne zostało zauważone, Razor opiera się na znaku @. A jeśli zechcemy, aby znak @ został potraktowany jako treść? W większości przypadków nic nie musimy robić, ponieważ Razor sam potrafi zdecydować, czy @ w danym kontekście służy jako znak specjalny, czy jako treść. Wyświetlając adres e-mail (np. contact@mail.com), parser analizuje kolejne słowa i stwierdzi, że w tym kontekście na pewno nie chodziło o zmienną tylko o zwykły tekst. Czasami jednak sytuacja jest nierozstrzygalna dla parsera i wtedy należy skorzystać z podwójnego znaku @@ – wówczas jawnie zostanie określone, że chodzi o tekst.

Szablony stron – master pages

Obsługa szablonów jest również prostsza i nie wymaga pisania długiej dyrektywy Page. Szablon definiujemy w pliku cshtml. Przykład (layout.cshtml):

<html>
   <head>
        <title>Tytul</title>
   </head>
<body>
  <div>Częśc wspólna</div>
  <div>@RenderBody()</div>
</body>
</html>

W szablonie definiujemy część, która będzie powtarzana na różnych stronach, oraz wywołujemy funkcje RenderBody w miejscu, gdzie ma zostać umieszczona część specyficzna dla danej strony. Następnie w konkretnej stronie podłączamy szablon za pomocą właściwości Layout:

@{
  Layout="Layout.cshtml";
}
<p>Jakis Tekst</p>

Wystarczy ustawić tylko pojedynczą właściwość – nie trzeba definiować długiej dyrektywy jak to miało miejsce w aspx. Następnie w pliku umieszczamy treść, która zostanie wstrzyknięta w miejsce wywołania funkcji RenderBody.

Istnieje również możliwość zdefiniowana sekcji w szablonie. Możemy w końcu szablon podzielić na części takie jak stopka, nagłówek, tytuł itp.  W takiej sytuacji należy wywołać funkcję RenderSection, przekazując jako parametry nazwę sekcji oraz wartość określającą, czy jest ona wymagana:

<html>
  <head>
        <title>@RenderSection("title", true)</title>
  </head>
<body>
  <div>Częśc wspólna</div>
  <div>@RenderBody()</div>
</body>
</html>

Następnie w szablonie wstrzykujemy tekst w odpowiednią sekcję za pomocą konstrukcji @section:

@{
  Layout="Layout.cshtml";
}
<p>Jakis Tekst</p>
@section title
{
 Tytul strony
}

Własny helper

Nierzadko generowanie widoku jest procesem skomplikowanym ze względu na bogate formatowanie HTML. Własne helpery umożliwiają wydzielenie powtarzających się fragmentów strony. Załóżmy, że często na stronie wyświetlamy kolekcję danych w formie tabelarycznej. Powtarzanie tej samej konstrukcji za każdym razem jest z pewnością mało eleganckim rozwiązaniem. Helper w działaniu przypomina procedurę – przyjmuje parametry i wykonuje jakąś czynność (w tym przypadku polegającą na wygenerowaniu treści). Przykład:

@helper FirstHelper(string text)
{   
  <p>@text</p>
}

Następnie w dowolnym miejscu strony możemy go wywołać:

   @FirstHelper("jakis tekst");

W praktyce oczywiście nie ma sensu pisanie tak prostego helpera. Przeważnie będzie to konstrukcja z pętlą i licznymi elementami HTML.

W Razor można również przekazywać parametry do wszelkich w funkcji w nieco inny sposób (inline):

   @Funkcja(parametr:"wartosc",parametr2:"wartosc2");

Zakończenie

Razor optymalizuje proces tworzenia widoków. Jedną z jego cech charakterystycznych jest prostota i przejrzystość. Wystarczy znajomość C#, aby swobodnie pisać elastyczne szablony. Visual Studio oferuje również wsparcie ze strony Intellisense, co bardzo ułatwia pracę. Warto podkreślić, że Razor i ASPX mogą być stosowane zamiennie dla różnych widoków tym samym projekcie. Oznacza to, że projekt rozpoczęty w poprzednich wersjach (w ASPX) można rozszerzać, wykorzystując silnik Razor.