Geeks With Blogs
Jakub Malinowski's blog The blog about ASP.NET

Ogłoszenia techniczne dotyczące wszystkich następnych postów:

uwagi w tekście, których nie ma w oryginale, oznaczone są kwadratowymi nawiasami  [ ];

tłumaczenia obowiązuje disclaimer.

 

Translation of original post by Phil Haack: / Tłumaczenie oryginalnego posta napisanego przez Phil’a Haack’a: http://haacked.com/archive/2009/08/04/default-templated-views.aspx

Uwaga! Ten post został napisany na podstawie ASP.NET MVC 2.0 Preview 1, a więc w przyszłości mogą się zmienić pewne szczegóły implementacyjne. Wkrótce spróbuję wrócić do ASP.NET MVC 1.0. :)

Wczoraj na spotkaniu z “The Gu” poruszliśmy kwestię automatycznych widoków. Wyobraź sobie, że możesz utworzyć jakiś obiekt modelu w akcji w kontrolerze, przekazać go do widoku, a ASP.NET MVC wygeneruje dla Ciebie ze schematu stronę do edycji lub przeglądania danych.

Właśnie wtedy świecąca żaróweczka pojawiła się nad głową Scott’a i nagle wspomniał on o pomyśle na realizację tego planu. Jego idea bardzo mi się spodobała i zdecydowałem, że dziś w nocy spróbuje zrealizować jego prototyp. Jednak zanim pokaże Ci ten prototyp, pozwól że wspomnę nieco o podłożu tego pomysłu.

Jednym z genialnych feature’ów ASP.NET MVC jest możliwość użycia widoków znajdujących się w folderze ~/Views/Shared dla wszystkich kontrolerów. Na przykład, załóżmy że chciałbyś stworzyć domyślny widok akcji nazwanej Index dla wszystkich kontrolerów. Możesz więc po prostu dodać widok Index do folderu Shared.

Tak więc każdy kontroler z akcją Index automatycznie użyje tego widoku, chyba że widok Index będzie się znajdował w folderze tego kontrolera.

Wobec tego, może moglibyśmy z tego skorzystać budując proste strony CRUD (Create, Read, Update, Delete). A jeśli umieścilibyśmy domyślne widoki o odpowiednich nazwach w folderze Shared? Co moglibyśmy umieścić w tych widokach? Cóż, więc oczywiście skorzystalibyśmy w nich z Templated Heades! [wspomniane też tutaj] W ten sposób dodając nowe akcje o nazwach zgodnych z konwencją widok byłby od razu gotowy – bez potrzeby tworzenia kolejnego widoku.

Stworzyłem dziś prototyp realizujący ten pomysł. Najpierw dodałem trzy widoki do folderu Shared – Details, Edit i Create.

 

Spójrzmy no widok Details, zobaczyć jak proste to jest to rozwiązanie.

<%@ Page Inherits="System.Web.Mvc.ViewPage"%>
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
    Details for <%= Html.Encode(ViewData.Eval("Title")) %>
</asp:Content>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">

    <fieldset class="default-view">
        <legend><%= Html.Encode(ViewData.Eval("Title")) %></legend>
    
        <% ViewData["__MyModel"] = Model; %>
        <%= Html.Display("__MyModel") %>
    </fieldset>
</asp:Content>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Widzimy tutaj niegeneryczną wersję ViewPage. Ponieważ ten widok może zostać użyty przez wiele kontrolerów, nie wiemy jaki typ modelu zostanie tutaj użyty (aż do momentu runtime’u oczywiście),  nie możemy użyć silnie typowanego widoku, możemy jednak użyć niegenerycznego helper’a Html.Display, aby wyświetlić model.

Dziwną rzecz, którą tu zauważysz, jest pewne oszustwo, którym musiałem się posłużyć. Dodałem obiekt modelu jako zwykły klucz do ViewData, a to ponieważ a Preview 1 znajduje się bug, który powoduje, że Html.Display(“”) nie używa ViewData.Model. Jestem jednak pewien, że zostanie to poprawione w przyszyłych release’ach.

Html.DisplayFor(m => m) również tutaj nie zadziała, ponieważ jako metoda generyczna opiera się o typ zadeklarowany (a nie runtime’u), a więc w tym przypadku będzie to Object.

Mając te widoki posiadamy już podstawowy CRUD (a właściwie Create, Edit i Details). Następnym razem tworząc nową akcję nazwaną tak jak te schematy, nie będę musiał tworzyć widoku.

Sprawdźmy to rozwiązanie w akcji. Kocham NerdDinner, ale jednak wolałbym tym razem użyć innego modelu. Wypróbujmy więc wojowników Ninja!

Najpierw stwórzmy prostą klasę Ninja.

 

public class Ninja
{
public string Name { get; set; }
public int ShurikenCount { get; set; }
public int BlowgunDartCount { get; set; }
public string Clan { get; set; }
}

 

 

 

 

 

 

 

 

 

Następnie utwórzmy NinjaController używając Add Controller z menu kontekstowego folderu Controllers.

 

Następnie otworzy nam się okienko, w którym można wybrać nazwę dla kontrolera i zaznaczyć opcję wygenerowania akcji ze schematu (który oczywiście można w pełni dostosować).

Wewnątrz nowego kontrolera stworzyłem przykładowego Ninja (jako statyczną klasę dla celów demonstracji) i zwracam ją jako model w akcji Details.

 

static Ninja _ninja = new Ninja { 
Name = "Ask a Ninja",
Clan = "Yokoyama",
BlowgunDartCount = 23,
ShurikenCount = 42 };

public ActionResult Details(int id)
{
ViewData["Title"] = "A Very Cool Ninja";
return View(_ninja);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

Zauważ, że umieściłem też wewnątrz ViewData tytuł (Title), bo wiem że widok go wyświetli. Mógłbym w rzeczywistości stworzyć NinjaViewModel zamiast osobno dodawać Title do ViewData, ale ze względu na fakt, że jest to tylko demonstracja – nie zrobiłem tego.

Kiedy otworzymy widok Details kontrolera Ninja, zobaczymy:

Dzięki domyślnym schematom, mogę zapomnieć o tworzeniu widoku i skupić się na tworzeniu metod akcji. Widok zostanie automatycznie utworzony.

Jeśli będę potrzebować drobnych zmian zawsze mogę oznaczyć klasy/właściwości atrybutami DataAnnotation, tutaj zmienię nazwy wyświetlanych właściwości.

 

public class Ninja
{
public string Name { get; set; }
[DisplayName("Shurikens")]
public int ShurikenCount { get; set; }
[DisplayName("Blowgun Darts")]
public int BlowgunDartCount { get; set; }
public string Clan { get; set; }
}

 

 

 

 

 

 

 

 

 

 

 

 

Jeśli zaniepokoiło Cię to, że obarczam model zadaniami należącymi do warstwy prezentacji, to uznajmy, że ten model został stworzony na potrzeby widoku. Dodatkowo w przyszłości zamierzamy dostarczyć rozwiązania, które pomogą przechowywać te ustawienia meta-data w innym miejscu. [oczywiście chodzi o definiowanie meta-data w runtime]

Kiedy zrekompiluję i odświeżę stronę, labele będą zawierać odpowiednie nazwy.

Alternatywnie mogę utworzyć nowy schemat wyświetlania dla Ninja. Wszystko, co muszę zrobić, to dodać folder DisplayTemplates do folderu Shared, a następnie utworzyć schemat dla typu Ninja.

Następnie w menu kontekstowym folderu wybieram Add View, zaznaczam opcję silnie-typowanego widoku i wybieram odpowiedni typ – wiem przecież, że template tworzę dla klasy Ninja.

 

Po dodaniu widoku, powinienem zobaczyć template w folderze DisplayTemplate. Mogę też otworzyć go do edycji i wprowadzić bardziej rozbudowane zmiany.

Po rekompilacji i odświeżeniu strony zobaczę:

Ostatecznie, jeśli potrzebuję jeszcze większej kontroli nad widokiem, mogę dodać widok Details do folderu widoków kontrolera Ninja, który da mi już całkowitą kontrolę i zakryje domyślny widok Details z folderu Shared.

Tak na ten moment wygląda realizacja pomysłu, który nazywam “domyślnymi schematami widoków” (“default templated views”). Pokazałem Ci pomysł, ale również sposób na wcielenie go do swoich aplikacji. Jak widzisz – możesz go z łatwością użyć, a nawet zmodyfikować, tak aby odpowiadał Twoim potrzebom.

Kiedy Scott o tym mówił, stwierdził nawet: “Czemu o tym wcześniej nie pomyślałem, przecież to oczywiste.” (albo coś w tym stylu, nie zapisałem tego).

A ja myślałem dokładnie tak samo, dopóki nie uświadomiłem sobie, że wcześniej nie mieliśmy takich helper’ów, więc domyślne schematy widoków nie miałyby sensu w ASP.NET MVC 1.0.

Ale w ASP.NET MVC 2.0 Preview 1 mamy takie helper’y, a ten post pokazuje pewne środki do budowania generowanych widoków w Twoich aplikacjach.

I zanim zapomnę, tutaj możesz pobrać mój przykładowy projekt Ninja.

Posted on Tuesday, August 4, 2009 2:34 PM Phil Haack's blog translations | Back to top

Related Posts on Geeks With Blogs Matching Categories

Comments on this post: Default Templated Views – you’ve been HAACKED – Tłumaczenie

Comments are closed.
Comments have been closed on this topic.
Copyright © jakubmal | Powered by: GeeksWithBlogs.net