Sdílet prostřednictvím


Část 3: Zobrazení a modely ViewModel

Jon Galloway

MVC Music Store je výuková aplikace, která představuje a vysvětluje podrobný postup použití ASP.NET MVC a sady Visual Studio pro vývoj pro web.

MVC Music Store je odlehčená ukázková implementace, která prodává hudební alba online a implementuje základní správu webu, přihlašování uživatelů a funkce nákupního košíku.

Tato série kurzů podrobně popisuje všechny kroky k vytvoření ukázkové aplikace ASP.NET MVC Music Store. Část 3 se zabývá zobrazeními a modely ViewModel.

Zatím jsme jenom vraceli řetězce z akcí kontroleru. Je to pěkný způsob, jak získat představu o tom, jak fungují kontrolery, ale není to způsob, jak byste chtěli vytvořit skutečnou webovou aplikaci. Budeme chtít lepší způsob, jak vygenerovat HTML zpět do prohlížečů, které navštíví naše stránky – jeden, kde můžeme použít soubory šablony ke snadnějšímu přizpůsobení obsahu HTML poslat zpět. To je přesně to, co Views dělají.

Přidání šablony zobrazení

Pokud chceme použít šablonu view-template, změníme metodu indexu HomeController tak, aby vracela hodnotu ActionResult, a vrátí metodu View(), jak je znázorněno níže:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

Výše uvedená změna značí, že místo vráceného řetězce chceme k vygenerování výsledku použít zobrazení.

Teď do projektu přidáme příslušnou šablonu zobrazení. Za tímto účelem umístíme textový kurzor do metody akce Index, klikneme pravým tlačítkem myši a vybereme Přidat zobrazení. Tím se zobrazí dialogové okno Přidat zobrazení:

Snímek obrazovky s nabídkou, která zobrazuje výběr zobrazení pro přidáníSnímek obrazovky s dialogovým oknem Přidat zobrazení s možnostmi nabídky pro výběr a přidání zobrazení

Dialogové okno Přidat zobrazení umožňuje rychle a snadno generovat soubory šablon zobrazení. Ve výchozím nastavení dialogové okno Přidat zobrazení předem vyplní název šablony zobrazení, která se má vytvořit, aby odpovídala metodě akce, která ji bude používat. Vzhledem k tomu, že jsme použili místní nabídku Přidat zobrazení v rámci metody akce Index() našeho homeControlleru, má výše uvedené dialogové okno Přidat zobrazení ve výchozím nastavení předvyplněný název zobrazení Index. V tomto dialogovém okně nemusíme měnit žádné možnosti, proto klikněte na tlačítko Přidat.

Když klikneme na tlačítko Přidat, Visual Web Developer pro nás vytvoří novou šablonu zobrazení Index.cshtml v adresáři \Views\Home a vytvoří složku, pokud ještě neexistuje.

Snímek obrazovky s rozevírací nabídkou Průzkumník řešení zobrazující různé soubory v obchodě M V C Music Store

Název a umístění složky souboru Index.cshtml je důležité a řídí se výchozími ASP.NET konvence vytváření názvů MVC. Název adresáře \Views\Home odpovídá kontroleru s názvem HomeController. Název šablony zobrazení Index odpovídá metodě akce kontroleru, která bude zobrazení zobrazovat.

ASP.NET MVC nám umožňuje vyhnout se tomu, abychom při použití této konvence vytváření názvů k vrácení zobrazení nemuseli explicitně zadávat název nebo umístění šablony zobrazení. Ve výchozím nastavení vykreslí šablonu zobrazení \Views\Home\Index.cshtml, když v rámci našeho kontroleleru HomeController napíšeme kód podobný následujícímu:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

Visual Web Developer vytvořil a otevřel šablonu zobrazení Index.cshtml poté, co jsme v dialogovém okně Přidat zobrazení klikli na tlačítko Přidat. Obsah souboru Index.cshtml je zobrazený níže.

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

V tomto zobrazení se používá syntaxe Razor, která je výstižnější než modul Web Forms zobrazení použitý v ASP.NET Web Forms a předchozích verzích ASP.NET MVC. Modul zobrazení Web Forms je stále k dispozici v ASP.NET MVC 3, ale mnoho vývojářů zjistilo, že modul zobrazení Razor ASP.NET vývoji MVC opravdu dobře vyhovuje.

První tři řádky nastaví název stránky pomocí ViewBag.Title. Na to, jak to funguje, se brzy podíváme podrobněji, ale nejdřív pojďme aktualizovat text nadpisu textu a podívat se na stránku. <Aktualizujte značku h2> tak, aby zobrazovala text "Toto je domovská stránka", jak je znázorněno níže.

@{
    ViewBag.Title = "Index";
}
<h2>This is the Home Page</h2>

Spuštění aplikace ukazuje, že náš nový text je viditelný na domovské stránce.

Snímek obrazovky s domovskou stránkou prohlížeče obchodu s hudbou a textem

Použití rozložení pro běžné prvky webu

Většina webů má obsah, který se sdílí mezi mnoha stránkami: navigace, zápatí, obrázky loga, odkazy na šablony stylů atd. Modul zobrazení Razor usnadňuje správu pomocí stránky s názvem _Layout.cshtml, která se automaticky vytvořila ve složce /Views/Shared.

Snímek obrazovky s rozevírací nabídkou souborů v obchodě Hudba s cestou ke sdílené složce umístěné ve složce zobrazení

Poklikáním na tuto složku zobrazíte obsah, který je zobrazený níže.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"     
            type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
            type="text/javascript"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

Obsah z jednotlivých zobrazení se zobrazí příkazem @RenderBody() a jakýkoli běžný obsah, který chceme zobrazit mimo, může být přidán do kódu _Layout.cshtml. Budeme chtít, aby náš obchod MVC Music Store měl společné záhlaví s odkazy na domovskou stránku a oblast Obchodu na všech stránkách webu, takže ho přidáme do šablony přímo nad tento @RenderBody() příkaz.

<!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.4.4.min.js")"
type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>
            ASP.NET MVC MUSIC STORE</h1>
        <ul id="navlist">
            <li class="first"><a href="/"
id="current">Home</a></li>
            <li><a
href="/Store/">Store</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>

Aktualizace šablony stylů

Prázdná šablona projektu obsahuje velmi zjednodušený soubor CSS, který obsahuje pouze styly používané k zobrazení ověřovacích zpráv. Náš návrhář poskytl několik dalších šablon stylů CSS a obrázků, které definují vzhled a chování našeho webu, takže je teď přidáme.

Aktualizovaný soubor CSS a obrázky jsou součástí adresáře Obsahu MvcMusicStore-Assets.zip který je k dispozici v MVC-Music-Store. Oba je vybereme v Průzkumníkovi Windows a uložíme je do složky Obsah našeho řešení ve Visual Web Developeru, jak je znázorněno níže:

Vedle sebe snímek obrazovky s adresářem obsahu a rozevírací nabídkou Úložiště hudby, který zobrazuje cestu k souboru ke složce images ve složce obsahu.

Zobrazí se výzva k potvrzení, jestli chcete přepsat existující soubor Site.css. Klikněte na Ano.

Snímek obrazovky s automaticky otevírané okno s upozorněním, které žádá o potvrzení akce přepsání dotazem, jestli chcete nahradit existující soubor

Složka Obsahu vaší aplikace se teď zobrazí takto:

Snímek obrazovky s úložištěm hudby, rozevírací nabídkou, zvýrazněnou složkou obsahu, zobrazující novou složku obrázků se seznamem obrázků pod

Teď spustíme aplikaci a podíváme se, jak změny vypadají na domovské stránce.

Snímek obrazovky s domovskou stránkou prohlížeče obchodu s hudbou a vybraným obrázkem a pod ním textem

  • Pojďme se podívat, co se změnilo: Metoda akce indexu HomeController našla a zobrazila šablonu \Views\Home\Index.cshtmlView, i když náš kód s názvem "return View()", protože naše šablona Zobrazení se řídí standardními zásadami vytváření názvů.
  • Domovská stránka zobrazuje jednoduchou uvítací zprávu, která je definována v šabloně zobrazení \Views\Home\Index.cshtml.
  • Domovská stránka používá šablonu _Layout.cshtml, takže uvítací zpráva je obsažena ve standardním rozložení HTML webu.

Použití modelu k předávání informací do našeho zobrazení

Šablona zobrazení, která jenom zobrazuje pevně zakódovaný kód HTML, neudělá velmi zajímavý web. Pokud chceme vytvořit dynamický web, budeme místo toho chtít předat informace z akcí kontroleru do šablon zobrazení.

Ve vzoru Model-View-Controller termín Model odkazuje na objekty, které představují data v aplikaci. Objekty modelu často odpovídají tabulkám v databázi, ale nemusí.

Metody akce kontroleru, které vrací ActionResult, můžou do zobrazení předat objekt modelu. To umožňuje kontroleru čistě zabalit všechny informace potřebné k vygenerování odpovědi a pak tyto informace předat šabloně Zobrazení, která použije k vygenerování příslušné odpovědi HTML. Nejsnadněji to pochopíte, když se zobrazí v akci, takže pojďme začít.

Nejprve vytvoříme několik tříd modelu, které budou představovat žánry a alba v našem obchodě. Začněme vytvořením třídy Žánr. Ve vašem projektu klikněte pravým tlačítkem na složku Models, zvolte možnost Přidat třídu a pojmenujte soubor "Žánr.cs".

Snímek obrazovky se třemi poli nabídek vedle sebe a zobrazenými pokyny k cestě k souboru zprava doleva k výběru třídy

Snímek obrazovky s možnostmi nabídky přidat novou položku zobrazující tři nabídky pro výběr šablony, styl řazení a typ; a pak dole na panelu názvových polí.

Potom do třídy, která byla vytvořena, přidejte vlastnost Název veřejného řetězce:

public class Genre
{
    public string Name { get; set; }
}

Poznámka: Pokud vás zajímá, notace { get; set; } využívá funkci automaticky implementovaných vlastností jazyka C#. To nám dává výhody vlastnosti, aniž by bylo nutné deklarovat záložní pole.

Pak stejným postupem vytvořte třídu Album (s názvem Album.cs), která má vlastnost Title a Žánr:

public class Album
{
    public string Title { get; set; }
    public Genre Genre { get; set; }
}

Teď můžeme upravit StoreController tak, aby používal zobrazení, která zobrazují dynamické informace z našeho modelu. Pokud bychom právě teď pro demonstrační účely pojmenovali alba na základě ID požadavku, mohli bychom tuto informaci zobrazit jako v následujícím zobrazení.

Snímek obrazovky s domovskou stránkou v prohlížeči, s logem obrázku, názvem aktuálního alba a kliknutím na tlačítka domů a obchodu v pravém horním rohu

Začneme tím, že změníme akci Store Details (Podrobnosti o obchodu), aby zobrazovala informace o jednom albu. Přidejte příkaz using do horní části třídy StoreControllers , aby zahrnoval obor názvů MvcMusicStore.Models, abychom nemuseli zadávat MvcMusicStore.Models.Album pokaždé, když chceme použít třídu alba. Část "usings" této třídy by se teď měla zobrazit následujícím způsobem.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.Models;

Dále aktualizujeme akci kontroleru Podrobnosti tak, aby vracela actionResult místo řetězce, jako jsme to udělali u metody Index homeController.

public ActionResult Details(int id)

Teď můžeme upravit logiku tak, aby se objekt Album vrátil do zobrazení. Později v tomto kurzu načteme data z databáze, ale v tuto chvíli použijeme "fiktivní data", abychom mohli začít.

public ActionResult Details(int id)
 {
    var album = new Album { Title = "Album " + id };
    return View(album);
 }

Poznámka: Pokud jazyk C# neznáte, můžete předpokládat, že hodnota var znamená, že proměnná alba je pozdně vázaná. To není správně – kompilátor jazyka C# používá odvození typu na základě toho, co přiřadíme proměnné, aby určil, že album je typu Album, a kompiluje místní proměnnou alba jako typ Album, takže získáme kontrolu kompilace a podporu editoru kódu sady Visual Studio.

Teď vytvoříme šablonu Zobrazení, která použije album k vygenerování odpovědi HTML. Než to uděláme, musíme sestavit projekt tak, aby dialogové okno Přidat zobrazení vědělo o nově vytvořené třídě Album. Projekt můžete sestavit tak, že vyberete položku nabídky Debug⇨Build MvcMusicStore (pokud chcete získat další kredit, můžete k sestavení projektu použít klávesovou zkratku Ctrl-Shift-B).

Snímek obrazovky s editorem dokumentů obchodu hudba s vybranou kartou build v rozevírací nabídce se zvýrazněnou možností

Teď, když jsme nastavili podpůrné třídy, jsme připraveni vytvořit šablonu Zobrazení. Klikněte pravým tlačítkem myši na metodu Details a vyberte Přidat zobrazení. z místní nabídky.

Snímek obrazovky s nabídkou šablony zobrazení, která se zobrazuje nad fragmentem kódu a zvýrazněnou možností přidat zobrazení

Vytvoříme novou šablonu zobrazení, jako jsme to udělali dříve s HomeControllerem. Protože ho vytváříme z StoreController, bude ve výchozím nastavení vygenerován v souboru \Views\Store\Index.cshtml.

Na rozdíl od dříve zaškrtneme políčko Vytvořit zobrazení silného typu. Pak vybereme naši třídu Album v rozevíracím seznamu Zobrazit datovou třídu. To způsobí, že dialogové okno Přidat zobrazení vytvoří šablonu zobrazení, která očekává, že objekt Album bude předán k použití.

Snímek obrazovky s oknem nabídky přidat zobrazení, na kterém je zaškrtávací políčko Vytvořit zobrazení silného typu, na které se dá kliknout, a třída modelu alba

Když klikneme na tlačítko Přidat, vytvoří se šablona zobrazení \Views\Store\Details.cshtml, která bude obsahovat následující kód.

@model MvcMusicStore.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>Details</h2>

Všimněte si prvního řádku, který označuje, že toto zobrazení je silného typu pro naši třídu Album. Modul zobrazení Razor chápe, že byl předán objekt Album, takže můžeme snadno přistupovat k vlastnostem modelu a dokonce mít výhodu IntelliSense v editoru Visual Web Developer.

<Aktualizujte značku h2> tak, aby zobrazovala vlastnost Název alba úpravou řádku tak, aby vypadal následovně.

<h2>Album: @Model.Title</h2>

Všimněte si, že technologie IntelliSense se aktivuje, když zadáte tečku za klíčovým slovem @Model a zobrazíte vlastnosti a metody, které třída Album podporuje.

Pojďme teď projekt znovu spustit a navštívit adresu URL /Store/Details/5. Zobrazí se podrobnosti o albu, jako jsou níže.

Snímek obrazovky s oknem prohlížeče domovské stránky, vlevo nahoře s logem obrázku a pod názvem alba

Teď provedeme podobnou aktualizaci pro metodu akce Store Browse ( Procházení storu). Aktualizujte metodu tak, aby vrátila ActionResult, a upravte logiku metody tak, aby se vytvořil nový objekt Genre a vrátil ho do Zobrazení.

public ActionResult Browse(string genre)
 {
    var genreModel = new Genre { Name = genre };
    return View(genreModel);
 }

Klikněte pravým tlačítkem myši na metodu Procházet a vyberte Přidat zobrazení. z místní nabídky a pak přidejte Zobrazení se silnými typy a přidejte do třídy Genre .

Snímek obrazovky s místní nabídkou, která zobrazuje vybranou možnost Vytvořit zobrazení se silnými typy a červeně za rámečkem aktuální třídy modelu

<Aktualizujte prvek h2> v kódu zobrazení (v /Views/Store/Browse.cshtml) tak, aby zobrazoval informace o žánru.

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>

Teď znovu spustíme projekt a přejdeme na /Store/Browse? Genre=Disco URL. Zobrazí se stránka Procházet jako níže.

Snímek obrazovky s oknem domovské stránky prohlížeče zobrazující pod obrázkem loga zprávu

Nakonec provedeme trochu složitější aktualizaci metody akce Store Index a zobrazíme seznam všech žánrů v našem obchodě. Provedeme to tak, že jako objekt modelu použijeme Seznam žánrů, nikoli jeden žánr.

public ActionResult Index()
{
    var genres = new List<Genre>
    {
        new Genre { Name = "Disco"},
        new Genre { Name = "Jazz"},
        new Genre { Name = "Rock"}
    };
    return View(genres);
 }

Klikněte pravým tlačítkem na metodu akce Uložit index a vyberte Přidat zobrazení jako předtím, jako třídu Model vyberte Žánr a stiskněte tlačítko Přidat.

Snímek obrazovky s nabídkou okna přidat zobrazení s výběrem třídy modelu v červeném poli a tlačítkem Přidat níže

Nejprve změníme @model deklaraci tak, aby naznačovala, že zobrazení bude očekávat několik objektů Žánr, a ne jen jeden. Změňte první řádek souboru /Store/Index.cshtml takto:

@model IEnumerable<MvcMusicStore.Models.Genre>

To říká modulu zobrazení Razor, že bude pracovat s objektem modelu, který může obsahovat několik objektů Žánr. Používáme IEnumerable<Žánr> spíše než Seznam<Žánr> , protože je obecnější, což nám umožňuje později změnit typ modelu na libovolný typ objektu, který podporuje rozhraní IEnumerable.

Dále si projdeme objekty Genre v modelu, jak je znázorněno v následujícím kódu dokončeného zobrazení.

@model IEnumerable<MvcMusicStore.Models.Genre>
@{
    ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
    Select from @Model.Count()
genres:</p>
<ul>
    @foreach (var genre in Model)
    {
        <li>@genre.Name</li>
    }
</ul>

Všimněte si, že při zadávání tohoto kódu máme plnou podporu Technologie IntelliSense, takže když zadáme "@Model.", uvidíme všechny metody a vlastnosti podporované IEnumerable typu Genre.

Snímek obrazovky s fragmentem kódu H T M L s řádkem nabídek a výběrem příkazu count <>

Visual Web Developer v naší smyčce "foreach" ví, že každá položka je typu Žánr, takže u každého typu Žánr vidíme IntelliSense.

Snímek obrazovky s kódem smyčky foreach s oknem rozevírací nabídky a vybranou možností name a vedle něj se zobrazí řetězec Název žánru.

Dále funkce generování prozkoumala objekt Genre a zjistila, že každý z nich bude mít vlastnost Name, takže je projde a zapíše. Vygeneruje také odkazy Upravit, Podrobnosti a Odstranit na každou jednotlivou položku. Toho využijeme později v našem manažerovi prodejny, ale prozatím bychom místo toho chtěli mít jednoduchý seznam.

Když aplikaci spustíme a přejdeme do /Store, uvidíme, že se zobrazí počet i seznam žánrů.

Snímek obrazovky s oknem prohlížeče, který zobrazuje název

Naše adresa URL /Store, která obsahuje seznam Žánry, aktuálně obsahuje názvy žánrů jednoduše jako prostý text. Pojďme to změnit tak, aby místo prostého textu byly názvy žánrů odkazující na příslušnou adresu URL /Store/Browse, takže kliknutím na hudební žánr, jako je Disco, přejdete na adresu URL /Store/Browse?žánr=Disco. Mohli bychom aktualizovat šablonu \Views\Store\Index.cshtml View tak, aby vypisovali tyto odkazy pomocí kódu podobného níže (nezadávejte ho, ale vylepšíme to):

<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

To funguje, ale mohlo by to později vést k problémům, protože spoléhá na pevně kódovaný řetězec. Pokud bychom například chtěli přejmenovat Kontroler, museli bychom v kódu hledat odkazy, které je potřeba aktualizovat.

Alternativním přístupem, který můžeme použít, je využít pomocnou metodu HTML. ASP.NET MVC obsahuje pomocné metody HTML, které jsou k dispozici v našem kódu šablony zobrazení a umožňují provádět různé běžné úlohy. Zvlášť užitečná je pomocná metoda Html.ActionLink(), která usnadňuje vytváření <> odkazů html a stará se o obtěžující podrobnosti, jako je kontrola, že cesty URL jsou správně zakódované.

Html.ActionLink() má několik různých přetížení, které umožňuje zadat tolik informací, kolik potřebujete pro odkazy. V nejjednodušším případě zadáte pouze text odkazu a metodu Action, na kterou se má přejít při kliknutí na hypertextový odkaz v klientovi. Pomocí následujícího volání můžeme například propojit metodu indexu "/Store/" na stránce Store Details s textem odkazu "Přejít na index obchodu":

@Html.ActionLink("Go
to the Store Index", "Index")

Poznámka: V tomto případě jsme nemuseli zadávat název kontroleru, protože jenom propojujeme jinou akci v rámci stejného kontroleru, která vykresluje aktuální zobrazení.

Naše odkazy na stránku Browse ale budou muset předat parametr, takže použijeme další přetížení metody Html.ActionLink, které přijímá tři parametry:

    1. Text odkazu, který zobrazí název žánru
    1. Název akce kontroleru (procházet)
    1. Hodnoty parametru směrování se zadáním názvu (Žánr) a hodnoty (Název žánru)

Když to všechno spojíme dohromady, tady je postup, jak napíšeme tyto odkazy na zobrazení Index storu:

<ul>
    @foreach (var genre in Model)
    {
        <li>@Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
    }
</ul>

Když teď projekt znovu spustíme a získáme přístup k adrese URL /Store/, zobrazí se seznam žánrů. Každý žánr představuje hypertextový odkaz – po kliknutí přejdeme na adresu URL /Store/Browse?žánr=[žánr].

Snímek obrazovky s oknem prohlížeče s nadpisem Procházet žánr se zprávou Select from 3 genres (Výběr ze 3 žánrů) následovanou třemi odrážkami s výběrem žánru

Kód HTML pro seznam žánrů vypadá takto:

<ul>
    <li><a href="/Store/Browse?genre=Disco">Disco</a>
</li>
    <li><a href="/Store/Browse?genre=Jazz">Jazz</a>
</li>
    <li><a href="/Store/Browse?genre=Rock">Rock</a>
</li>
</ul>