Przekazywanie danych do stron wzorcowych widoku (C#)

przez Microsoft

Pobierz plik PDF

Celem tego samouczka jest wyjaśnienie, jak można przekazać dane z kontrolera do strony wzorcowej widoku. Analizujemy dwie strategie przekazywania danych do strony wzorcowej widoku. Najpierw omówimy łatwe rozwiązanie, które powoduje, że aplikacja, która jest trudna do utrzymania. Następnie badamy znacznie lepsze rozwiązanie, które wymaga nieco więcej wstępnej pracy, ale powoduje znacznie bardziej łagodnące zastosowanie.

Przekazywanie danych do wyświetlania stron wzorcowych

Celem tego samouczka jest wyjaśnienie, jak można przekazać dane z kontrolera do strony wzorcowej widoku. Analizujemy dwie strategie przekazywania danych do strony wzorcowej widoku. Najpierw omówimy łatwe rozwiązanie, które powoduje, że aplikacja, która jest trudna do utrzymania. Następnie badamy znacznie lepsze rozwiązanie, które wymaga nieco więcej wstępnej pracy, ale powoduje znacznie bardziej łagodnące zastosowanie.

The Problem

Wyobraź sobie, że budujesz aplikację bazy danych filmów i chcesz wyświetlić listę kategorii filmów na każdej stronie w aplikacji (zobacz Rysunek 1). Wyobraź sobie ponadto, że lista kategorii filmów jest przechowywana w tabeli bazy danych. W takim przypadku warto byłoby pobrać kategorie z bazy danych i renderować listę kategorii filmów na stronie 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ć pełnowymiarowy obraz)

Oto problem. Jak pobrać listę kategorii filmów na stronie wzorcowej? Jest kuszące, aby wywołać metody klas modelu bezpośrednio na stronie wzorcowej. Innymi słowy jest kuszące, aby dołączyć kod do pobierania danych z bazy danych bezpośrednio na stronie wzorcowej. Jednak pomijając kontrolery MVC, aby uzyskać dostęp do bazy danych naruszyłby czyste oddzielenie problemów, która jest jedną z podstawowych zalet tworzenia aplikacji MVC.

W aplikacji MVC chcesz, aby wszystkie interakcje między widokami MVC i modelu MVC być obsługiwane przez kontrolery MVC. Ten rozdzielenie dotyczy skutkuje bardziej łagodnym, elastycznym i sprawdzalnym zastosowaniem.

W aplikacji MVC wszystkie dane przekazywane do widoku — w tym strony wzorcowej widoku — powinny być przekazywane do widoku przez akcję kontrolera. Ponadto dane powinny być przekazywane, 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.

Należy wziąć pod uwagę kontroler w wykazie 1. Udostępnia dwie akcje Index() o Details()nazwie i . Metoda Index() akcji zwraca każdy film w tabeli Bazy danych Filmy. Metoda Details() akcji zwraca każdy film w określonej kategorii filmu.

Lista 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();
          }
     }
}

Należy zauważyć, że akcje Index() i Details() dodają dwa elementy do wyświetlania danych. Akcja Index() dodaje dwa klawisze: kategorie i filmy. Klucz kategorii reprezentuje listę kategorii filmów wyświetlanych na stronie wzorcowej widoku. Klucz filmy reprezentuje listę filmów wyświetlanych na stronie Widok indeksu.

Akcja Details() dodaje również dwa klucze o nazwie kategorie i filmy. Klucz kategorii po raz kolejny reprezentuje listę kategorii filmów wyświetlanych na stronie wzorcowej widoku. Klucz filmy reprezentuje listę filmów w określonej kategorii wyświetlaną na stronie widok szczegóły (patrz rysunek 2).

Widok Szczegóły

Rysunek 02: Widok Szczegóły(Kliknij, aby wyświetlić pełnowymiarowy obraz)

Widok indeksu znajduje się w wykazie 2. To po prostu iteruje przez listę filmów reprezentowanych przez element filmów w danych widoku.

Lista 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>

Strona wzorcowa widoku znajduje się w wykazie 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="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>

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.

Więc, co jest nie tak z tym rozwiązaniem? Problem polega na tym, że to rozwiązanie narusza zasadę DRY (Don't Repeat Yourself). Każda akcja kontrolera musi dodać tę samą listę kategorii filmów, aby wyświetlić dane. Mając zduplikowany kod w aplikacji sprawia, że aplikacja znacznie trudniejsze do utrzymania, dostosować i zmodyfikować.

Dobre rozwiązanie

W tej sekcji zbadamy alternatywne i lepsze rozwiązanie 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 w kontrolerze aplikacji.

ApplicationController Klasa znajduje się w aukcji 4.

Lista 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;
          }

     }
}

Istnieją trzy rzeczy, które należy zauważyć o kontrolerze aplikacji w wykazie 4. Najpierw należy zauważyć, że klasa dziedziczy z podstawowej klasy System.Web.Mvc.Controller. Kontroler aplikacji jest klasą kontrolera.

Po drugie należy zauważyć, że klasa kontrolera aplikacji jest klasą abstrakcyjną. Klasa abstrakcyjna jest klasą, która musi być zaimplementowana przez klasę betonu. Ponieważ kontroler aplikacji jest klasą abstrakcyjną, nie można wywołać żadnych metod zdefiniowanych bezpośrednio w klasie. Jeśli spróbujesz wywołać Application klasy bezpośrednio wtedy pojawi się komunikat o błędzie zasobu nie można odnaleźć.

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

Kontroler Filmy w wykazie 5 dziedziczy z kontrolera aplikacji.

Lista 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, podobnie jak kontroler home omówione w poprzedniej sekcji, Index() Details()udostępnia dwie metody akcji o nazwie i . Należy zauważyć, że lista kategorii filmów wyświetlanych przez stronę wzorcową widoku Index() Details() nie jest dodawana do wyświetlania danych w metodzie lub. Ponieważ kontroler Filmy dziedziczy z kontrolera aplikacji, lista kategorii filmów jest dodawana do automatycznego wyświetlania danych.

Należy zauważyć, ż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: konstruktorze dla kontrolera aplikacji.

Podsumowanie

W tym samouczku omówiliśmy dwa podejścia do przekazywania danych widoku z kontrolera do strony wzorcowej widoku. Najpierw zbadaliśmy proste, ale trudne do utrzymania podejście. W pierwszej sekcji omówiliśmy sposób dodawania danych widoku dla strony wzorcowej widoku w każdej akcji kontrolera w aplikacji. Doszliśmy do wniosku, że było to złe podejście, ponieważ narusza zasadę DRY (Don't Repeat Yourself).

Następnie zbadaliś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 kontrolerze aplikacji. W ten sposób można uniknąć zduplikowanego kodu podczas przekazywania danych do strony wzorcowej widoku w aplikacji ASP.NET MVC.