Předání dat stránkám předlohy pro zobrazení (C#)
od Microsoftu
Cílem tohoto kurzu je vysvětlit, jak můžete předat data z kontroleru na stránku předlohy zobrazení. Prozkoumáme dvě strategie předávání dat na stránku předlohy zobrazení. Nejprve probereme jednoduché řešení, které vede k aplikaci, která se obtížně udržuje. Dále prozkoumáme mnohem lepší řešení, které vyžaduje trochu více počáteční práce, ale výsledkem je mnohem lépe udržovatelná aplikace.
Předávání dat na stránky předlohy zobrazení
Cílem tohoto kurzu je vysvětlit, jak můžete předat data z kontroleru na stránku předlohy zobrazení. Prozkoumáme dvě strategie předávání dat na stránku předlohy zobrazení. Nejprve probereme jednoduché řešení, které vede k aplikaci, která se obtížně udržuje. Dále prozkoumáme mnohem lepší řešení, které vyžaduje trochu více počáteční práce, ale výsledkem je mnohem lépe udržovatelná aplikace.
Problém
Představte si, že vytváříte aplikaci filmové databáze a chcete zobrazit seznam kategorií filmů na každé stránce aplikace (viz Obrázek 1). Představte si navíc, že seznam kategorií filmů je uložený v databázové tabulce. V takovém případě by bylo vhodné načíst kategorie z databáze a vykreslit seznam kategorií filmů v rámci stránky předlohy zobrazení.
Obrázek 01: Zobrazení kategorií filmů na stránce předlohy zobrazení (kliknutím zobrazíte obrázek v plné velikosti)
Tady je problém. Jak načtete seznam kategorií filmů na stránce předlohy? Je lákavé volat metody tříd modelu přímo na stránce předlohy. Jinými slovy, je lákavé zahrnout kód pro načtení dat z databáze přímo na stránku předlohy. Obejití kontrolerů MVC pro přístup k databázi by však narušilo čisté oddělení obav, které je jednou z hlavních výhod vytváření aplikace MVC.
V aplikaci MVC chcete, aby veškerou interakci mezi zobrazeními MVC a modelem MVC zpracovávaly kontrolery MVC. Toto oddělení obav má za následek lépe udržovatelnou, přizpůsobitelnou a testovatelnou aplikaci.
V aplikaci MVC by všechna data předaná do zobrazení – včetně stránky předlohy zobrazení – měla být předána zobrazení pomocí akce kontroleru. Kromě toho by se data měla předávat s využitím výhod zobrazení dat. Ve zbývající části tohoto kurzu prozkoumám dvě metody předávání dat zobrazení na stránku předlohy zobrazení.
Jednoduché řešení
Začněme nejjednodušším řešením předávání dat zobrazení z kontroleru na stránku předlohy zobrazení. Nejjednodušším řešením je předat data zobrazení pro stránku předlohy v každé akci kontroleru.
Vezměte v úvahu kontroler ve výpisu 1. Zveřejňuje dvě akce s názvem Index()
a Details()
. Metoda Index()
akce vrátí všechny filmy v tabulce databáze Filmy. Metoda Details()
akce vrátí všechny filmy v určité kategorii filmů.
Výpis 1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
private MovieDataContext _dataContext = new MovieDataContext();
/// <summary>
/// Show list of all movies
/// </summary>
public ActionResult Index()
{
ViewData["categories"] = from c in _dataContext.MovieCategories
select c;
ViewData["movies"] = from m in _dataContext.Movies
select m;
return View();
}
/// <summary>
/// Show list of movies in a category
/// </summary>
public ActionResult Details(int id)
{
ViewData["categories"] = from c in _dataContext.MovieCategories
select c;
ViewData["movies"] = from m in _dataContext.Movies
where m.CategoryId == id
select m;
return View();
}
}
}
Všimněte si, že akce Index() a Details() přidávají dvě položky pro zobrazení dat. Akce Index() přidá dva klíče: kategorie a filmy. Klíč kategorií představuje seznam kategorií filmů zobrazených stránkou předlohy zobrazení. Klíč filmy představuje seznam filmů zobrazených na stránce Index zobrazení.
Akce Podrobnosti() také přidá dva klíče pojmenované kategorie a filmy. Klíč categories opět představuje seznam kategorií filmů zobrazených stránkou předlohy zobrazení. Klíč filmy představuje seznam filmů v určité kategorii zobrazený na stránce zobrazení Podrobnosti (viz Obrázek 2).
Obrázek 02: Zobrazení podrobností (kliknutím zobrazíte obrázek v plné velikosti)
Zobrazení indexu je obsaženo ve výpisu 2. Jednoduše iteruje seznam filmů reprezentovaných položkou filmy v zobrazených datech.
Výpis 2 – Views\Home\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<ul>
<% foreach (var m in (IEnumerable<Movie>)ViewData["movies"])
{ %>
<li><%= m.Title %></li>
<% } %>
</ul>
</asp:Content>
Stránka předlohy zobrazení je obsažena ve výpisu 3. Stránka předlohy zobrazení iteruje a vykresluje všechny kategorie filmů reprezentované položkou kategorií z dat zobrazení.
Výpis 3 – Views\Shared\Site.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="MvcApplication1.Views.Shared.Site" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div>
<h1>My Movie Website</h1>
<% foreach (var c in (IEnumerable<MovieCategory>)ViewData["categories"])
{%>
<%= Html.ActionLink(c.Name, "Details", new {id=c.Id} ) %>
<% } %>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
Všechna data se předávají zobrazení a stránce předlohy zobrazení prostřednictvím dat zobrazení. To je správný způsob, jak předat data na stránku předlohy.
Co je tedy na tomto řešení špatného? Problém je v tom, že toto řešení porušuje zásadu DRY (Neopakovat se). Každá akce ovladače musí přidat stejný seznam kategorií filmů pro zobrazení dat. Duplicitní kód v aplikaci ztěžuje údržbu, přizpůsobení a úpravy aplikace.
Dobré řešení
V této části prozkoumáme alternativní a lepší řešení pro předávání dat z akce kontroleru na stránku předlohy zobrazení. Místo přidání kategorií filmů pro stránku předlohy v každé akci ovladače přidáme kategorie filmů do dat zobrazení pouze jednou. Všechna data zobrazení používaná stránkou předlohy zobrazení se přidají do kontroleru aplikace.
ApplicationController Třída je obsažena ve výpisu 4.
Výpis 4 – Controllers\ApplicationController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public abstract class ApplicationController : Controller
{
private MovieDataContext _dataContext = new MovieDataContext();
public MovieDataContext DataContext
{
get { return _dataContext; }
}
public ApplicationController()
{
ViewData["categories"] = from c in DataContext.MovieCategories
select c;
}
}
}
Existují tři věci, které byste si měli všimnout kontroleru aplikace ve výpisu 4. Nejprve si všimněte, že třída dědí ze základní třídy System.Web.Mvc.Controller. Kontroler aplikací je třída kontroleru.
Za druhé si všimněte, že třída kontroleru aplikací je abstraktní třída. Abstraktní třída je třída, která musí být implementována konkrétní třídou. Vzhledem k tomu, že aplikační kontroler je abstraktní třída, nelze přímo vyvolat žádné metody definované ve třídě. Pokud se pokusíte vyvolat třídu Aplikace přímo, zobrazí se chybová zpráva Prostředek se nenašel.
Za třetí si všimněte, že kontroler aplikace obsahuje konstruktor, který přidává seznam kategorií filmů pro zobrazení dat. Každá třída kontroleru, která dědí z kontroleru aplikace, volá konstruktor kontroleru aplikace automaticky. Kdykoli zavoláte nějakou akci na libovolném kontroleru, který dědí z kontroleru aplikace, kategorie filmů se automaticky zahrnou do dat zobrazení.
Řadič Filmy ve výpisu 5 dědí z kontroleru aplikace.
Výpis 5 – Controllers\MoviesController.cs
using System.Linq;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class MoviesController : ApplicationController
{
/// <summary>
/// Show list of all movies
/// </summary>
public ActionResult Index()
{
ViewData["movies"] = from m in DataContext.Movies
select m;
return View();
}
/// <summary>
/// Show list of movies in a category
/// </summary>
public ActionResult Details(int id)
{
ViewData["movies"] = from m in DataContext.Movies
where m.CategoryId == id
select m;
return View();
}
}
}
Kontroler Filmy, stejně jako řadič Home probíraný v předchozí části, zveřejňuje dvě metody akce s názvem Index()
a Details()
. Všimněte si, že seznam kategorií filmů zobrazených stránkou předlohy zobrazení není přidán do zobrazení dat v Index()
metodě nebo Details()
. Vzhledem k tomu, že řadič Filmy dědí z kontroleru aplikace, přidá se seznam kategorií filmů pro zobrazení dat automaticky.
Všimněte si, že toto řešení pro přidání dat zobrazení pro stránku předlohy zobrazení neporušuje zásadu DRY (Neopakovat se). Kód pro přidání seznamu kategorií filmů pro zobrazení dat je obsažen pouze v jednom umístění: konstruktoru pro kontroler aplikace.
Souhrn
V tomto kurzu jsme probrali dva přístupy k předávání dat zobrazení z kontroleru na stránku předlohy zobrazení. Nejprve jsme prozkoumali jednoduchý, ale obtížně udržovatelné přístup. V první části jsme probrali, jak můžete přidat data zobrazení pro stránku předlohy zobrazení do každé akce kontroleru ve vaší aplikaci. Dospěli jsme k závěru, že se jedná o špatný přístup, protože porušuje zásadu DRY (Neopakovat se).
Dále jsme prozkoumali mnohem lepší strategii pro přidání dat vyžadovaných stránkou předlohy zobrazení pro zobrazení dat. Místo přidání dat zobrazení do každé akce kontroleru jsme data zobrazení přidali pouze jednou v rámci kontroleru aplikace. Tímto způsobem se můžete vyhnout duplicitnímu kódu při předávání dat na stránku předlohy zobrazení v aplikaci ASP.NET MVC.