Przekazywanie danych do stron wzorcowych widoku (VB)

autor: Microsoft

Pobierz plik PDF

Celem tego samouczka jest wyjaśnienie sposobu przekazywania danych z kontrolera do strony wzorcowej widoku. Analizujemy dwie strategie przekazywania danych do strony wzorcowej widoku. Po pierwsze omówimy łatwe rozwiązanie, które powoduje, że aplikacja jest trudna do utrzymania. Następnie przeanalizujemy znacznie lepsze rozwiązanie, które wymaga nieco więcej pracy początkowej, ale skutkuje znacznie bardziej konserwalną aplikacją.

Przekazywanie danych do stron wzorcowych widoku

Celem tego samouczka jest wyjaśnienie sposobu przekazywania danych z kontrolera do strony wzorcowej widoku. Analizujemy dwie strategie przekazywania danych do strony wzorcowej widoku. Po pierwsze omówimy łatwe rozwiązanie, które powoduje, że aplikacja jest trudna do utrzymania. Następnie przeanalizujemy znacznie lepsze rozwiązanie, które wymaga nieco więcej pracy początkowej, ale skutkuje znacznie bardziej konserwalną aplikacją.

The Problem

Załóżmy, że tworzysz aplikację bazy danych filmów i chcesz wyświetlić listę kategorii filmów na każdej stronie w aplikacji (zobacz Rysunek 1). Załóżmy ponadto, że lista kategorii filmów jest przechowywana w tabeli bazy danych. W takim przypadku warto pobrać kategorie z bazy danych i renderować listę kategorii filmów w obrębie strony wzorcowej widoku.

Wyświetlanie kategorii filmów na stronie wzorcowej widoku

Rysunek 01. Wyświetlanie kategorii filmów na stronie wzorcowej widoku (kliknij, aby wyświetlić obraz pełnowymiarowy)

Oto problem. Jak pobrać listę kategorii filmów na stronie wzorcowej? Kuszące jest bezpośrednie wywołanie metod klas modelu na stronie wzorcowej. Innymi słowy, kuszące jest dołączenie kodu do pobierania danych z bazy danych bezpośrednio na stronie wzorcowej. Jednak pomijanie kontrolerów MVC w celu uzyskania dostępu do bazy danych naruszałoby czyste rozdzielenie problemów, które są jedną z podstawowych zalet tworzenia aplikacji MVC.

W aplikacji MVC chcesz, aby cała interakcja między widokami MVC i modelem MVC została obsłużona przez kontrolery MVC. Takie rozdzielenie obaw powoduje zwiększenie możliwości utrzymania, dostosowania i testowania aplikacji.

W aplikacji MVC wszystkie dane przekazane do widoku — w tym strona wzorcowa widoku — powinny być przekazywane do widoku przez akcję kontrolera. Ponadto dane powinny zostać przekazane, korzystając z danych widoku. W pozostałej części tego samouczka badam dwie metody przekazywania danych widoku do strony wzorcowej widoku.

Proste rozwiązanie

Zacznijmy od najprostszego rozwiązania do przekazywania danych widoku z kontrolera do strony wzorcowej widoku. Najprostszym rozwiązaniem jest przekazanie danych widoku dla strony wzorcowej w każdej akcji kontrolera.

Rozważ kontroler na liście 1. Uwidacznia dwie akcje o nazwie Index() i Details(). Metoda Index() akcji zwraca każdy film w tabeli bazy danych Filmy. Metoda Details() akcji zwraca każdy film w określonej kategorii filmów.

Lista 1 — Controllers\HomeController.vb

<HandleError()> _
Public Class HomeController
     Inherits System.Web.Mvc.Controller

     Private _dataContext As New MovieDataContext()

     ''' <summary>

     ''' Show list of all movies
     ''' </summary>
     Function Index()
          ViewData("categories") = From c In _dataContext.MovieCategories _
                    Select c
          ViewData("movies") = From m In _dataContext.Movies _
                    Select m
          Return View()
     End Function

     ''' <summary>
     ''' Show list of movies in a category
     ''' </summary>

     Function Details(ByVal id As Integer)
          ViewData("categories") = From c In _dataContext.MovieCategories _
                    Select c
          ViewData("movies") = From m In _dataContext.Movies _
                    Where m.CategoryId = id _
                    Select m
          Return View()
     End Function

End Class

Zwróć uwagę, że obie akcje Index() i Details() dodają dwa elementy, aby wyświetlić dane. Akcja Index() dodaje dwa klucze: kategorie i filmy. Klucz kategorii reprezentuje listę kategorii filmów wyświetlanych na stronie wzorcowej widoku. Klucz filmów reprezentuje listę filmów wyświetlanych na stronie Widok indeksu.

Akcja Details() dodaje również dwa klucze o nazwach kategorii i filmów. Klucz kategorii po raz kolejny reprezentuje listę kategorii filmów wyświetlanych na stronie wzorcowej widoku. Klucz filmów reprezentuje listę filmów w określonej kategorii wyświetlanej na stronie Widok szczegółów (zobacz Rysunek 2).

Widok Szczegóły

Rysunek 02. Widok szczegółów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Widok indeksu znajduje się na liście 2. Po prostu iteruje po liście filmów reprezentowanych przez element filmów w danych widoku.

Lista 2 — Views\Home\Index.aspx

<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="MvcApplication1.Index" %>

<%@ Import Namespace="MvcApplication1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

<ul>

<%  For Each m In ViewData("movies")%>

     <li><%= m.Title %></li>

<% Next%>
</ul>

</asp:Content>

Strona wzorcowa widoku znajduje się na liście 3. Strona wzorcowa widoku iteruje i renderuje wszystkie kategorie filmów reprezentowane przez element kategorii z danych widoku.

Lista 3 — Views\Shared\Site.master

<%@ Master Language="VB" AutoEventWireup="false" CodeBehind="Site.Master.vb" Inherits="MvcApplication1.Site" %>

<%@ Import Namespace="MvcApplication1" %>
<!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>

          <% For Each c In ViewData("categories")%>

               <%=Html.ActionLink(c.Name, "Details", New With {.id = c.Id})%> 

          <% Next%>


          <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

          </asp:ContentPlaceHolder>
     </div>
</body>
</html>

Wszystkie dane są przekazywane do widoku i strony wzorcowej widoku za pośrednictwem danych widoku. Jest to prawidłowy sposób przekazywania danych do strony wzorcowej.

Co więc jest nie tak z tym rozwiązaniem? Problem polega na tym, że to rozwiązanie narusza zasadę DRY (Nie powtarzaj siebie). Każda akcja kontrolera musi dodać tę samą listę kategorii filmów, aby wyświetlić dane. Zduplikowanie kodu w aplikacji znacznie utrudnia konserwację, dostosowywanie i modyfikowanie aplikacji.

Dobre rozwiązanie

W tej sekcji przyjrzymy się alternatywnemu i lepszemu rozwiązaniu do przekazywania danych z akcji kontrolera do strony wzorcowej widoku. Zamiast dodawać kategorie filmów dla strony wzorcowej w każdej akcji kontrolera, dodajemy kategorie filmów do danych widoku tylko raz. Wszystkie dane widoku używane przez stronę wzorcową widoku są dodawane do kontrolera aplikacji.

Klasa ApplicationController jest zawarta w liście 4.

Klasa ApplicationController jest zawarta w liście 4.

Lista 4 — Controllers\ApplicationController.vb

Public MustInherit Class ApplicationController
     Inherits System.Web.Mvc.Controller

     Private _dataContext As New MovieDataContext()

     Public ReadOnly Property DataContext() As MovieDataContext
          Get

               Return _dataContext
          End Get
     End Property


     Sub New()
          ViewData("categories") = From c In DataContext.MovieCategories _
                    Select c
     End Sub

End Class

Istnieją trzy elementy, które należy zauważyć na temat kontrolera aplikacji na liście 4. Najpierw należy zauważyć, że klasa dziedziczy z podstawowej klasy System.Web.Mvc.Controller. Kontroler aplikacji jest klasą kontrolera.

Po drugie zwróć uwagę, że klasa kontrolera aplikacji jest klasą MustInherit. Klasa MustInherit jest klasą, która musi zostać zaimplementowana przez betonową klasę. Ponieważ kontroler aplikacji jest klasą MustInherit, nie można bezpośrednio wywołać żadnych metod zdefiniowanych w klasie. Jeśli spróbujesz wywołać klasę Application bezpośrednio, zostanie wyświetlony komunikat o błędzie Nie można odnaleźć zasobu.

Po trzecie zwróć uwagę, że kontroler aplikacji zawiera konstruktor, który dodaje listę kategorii filmów do wyświetlania danych. Każda klasa kontrolera dziedziczona z kontrolera aplikacji automatycznie wywołuje konstruktor kontrolera aplikacji. Za każdym razem, gdy wywołujesz dowolną akcję na dowolnym kontrolerze, który dziedziczy z kontrolera aplikacji, kategorie filmów są automatycznie uwzględniane w danych widoku.

Kontroler filmów na liście 5 dziedziczy z kontrolera aplikacji.

Lista 5 — Controllers\MoviesController.vb

<HandleError()> _
Public Class MoviesController
     Inherits ApplicationController

     ''' <summary>
     ''' Show list of all movies
     ''' </summary>
     Function Index()
          ViewData("movies") = From m In DataContext.Movies _
                    Select m
          Return View()

      End Function

     ''' <summary>
     ''' Show list of movies in a category
     ''' </summary>
     Function Details(ByVal id As Integer)
          ViewData("movies") = From m In DataContext.Movies _
                    Where m.CategoryId = id _
                    Select m
          Return View()
     End Function

End Class

Kontroler filmy, podobnie jak kontroler Home omówiony w poprzedniej sekcji, uwidacznia dwie metody akcji o nazwie Index() i Details(). Zwróć uwagę, że lista kategorii filmów wyświetlanych przez stronę wzorcową widoku nie jest dodawana do wyświetlania danych w metodzie Index() lub Details() . Ponieważ kontroler filmy dziedziczy z kontrolera aplikacji, lista kategorii filmów jest dodawana do automatycznego wyświetlania danych.

Zwróć uwagę, że to rozwiązanie do dodawania danych widoku dla strony wzorcowej widoku nie narusza zasady DRY (Nie powtarzaj siebie). Kod dodawania listy kategorii filmów do wyświetlania danych znajduje się tylko w jednej lokalizacji: konstruktor kontrolera aplikacji.

Podsumowanie

W tym samouczku omówiliśmy dwie metody przekazywania danych widoku z kontrolera do strony wzorcowej widoku. Po pierwsze zbadaliśmy proste, ale trudne do utrzymania podejście. W pierwszej sekcji omówiono sposób dodawania danych widoku dla strony wzorcowej widoku w każdej akcji kontrolera w aplikacji. Doszliśmy do wniosku, że jest to złe podejście, ponieważ narusza zasadę DRY (Nie powtarzaj siebie).

Następnie przeanalizowaliśmy znacznie lepszą strategię dodawania danych wymaganych przez stronę wzorcową widoku do wyświetlania danych. Zamiast dodawać dane widoku w każdej akcji kontrolera, dodaliśmy dane widoku tylko raz w ramach kontrolera aplikacji. Dzięki temu można uniknąć zduplikowania kodu podczas przekazywania danych do strony wzorcowej widoku w aplikacji ASP.NET MVC.