Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
da Microsoft
L'obiettivo di questa esercitazione è spiegare come passare i dati da un controller a una pagina master di visualizzazione. Vengono esaminate due strategie per passare i dati a una pagina master di visualizzazione. In primo luogo, viene descritta una soluzione semplice che comporta un'applicazione che è difficile da gestire. Successivamente, esaminiamo una soluzione molto migliore che richiede un po ' di lavoro iniziale, ma comporta un'applicazione molto più gestibile.
Passaggio di dati alla visualizzazione di pagine master
L'obiettivo di questa esercitazione è spiegare come passare i dati da un controller a una pagina master di visualizzazione. Vengono esaminate due strategie per passare i dati a una pagina master di visualizzazione. In primo luogo, viene descritta una soluzione semplice che comporta un'applicazione che è difficile da gestire. Successivamente, esaminiamo una soluzione molto migliore che richiede un po ' di lavoro iniziale, ma comporta un'applicazione molto più gestibile.
Problema
Si supponga di creare un'applicazione di database di film e di visualizzare l'elenco delle categorie di film in ogni pagina dell'applicazione (vedere la figura 1). Si supponga, inoltre, che l'elenco delle categorie di film sia archiviato in una tabella di database. In questo caso, sarebbe opportuno recuperare le categorie dal database e eseguire il rendering dell'elenco delle categorie di film all'interno di una pagina master di visualizzazione.
Figura 01: Visualizzazione di categorie di film in una pagina master di visualizzazione (fare clic per visualizzare l'immagine a dimensioni complete)
Ecco il problema. Come si recupera l'elenco delle categorie di film nella pagina master? È tentato di chiamare direttamente i metodi delle classi di modello nella pagina master. In altre parole, è tentato di includere il codice per recuperare i dati dal database direttamente nella pagina master. Tuttavia, ignorare i controller MVC per accedere al database viola la separazione pulita dei problemi che è uno dei vantaggi principali della creazione di un'applicazione MVC.
In un'applicazione MVC si vuole che tutte le interazioni tra le visualizzazioni MVC e il modello MVC vengano gestite dai controller MVC. Questa separazione dei problemi comporta un'applicazione più gestibile, adattabile e testable.
In un'applicazione MVC, tutti i dati passati a una visualizzazione, inclusa una pagina master di visualizzazione, devono essere passati a una visualizzazione da un'azione del controller. Inoltre, i dati devono essere passati sfruttando i dati di visualizzazione. Nella parte restante di questa esercitazione vengono esaminati due metodi per passare i dati di visualizzazione a una pagina master di visualizzazione.
Soluzione semplice
Iniziamo con la soluzione più semplice per passare i dati di visualizzazione da un controller a una pagina master di visualizzazione. La soluzione più semplice consiste nel passare i dati di visualizzazione per la pagina master in ogni e ogni azione del controller.
Prendere in considerazione il controller nell'elenco 1. Espone due azioni denominate Index()
e Details()
. Il Index()
metodo azione restituisce ogni filmato nella tabella di database Movies. Il Details()
metodo azione restituisce ogni filmato in una determinata categoria di film.
Elenco 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();
}
}
}
Si noti che entrambe le azioni Index() e Details() aggiungono due elementi per visualizzare i dati. L'azione Index() aggiunge due chiavi: categorie e film. La chiave delle categorie rappresenta l'elenco delle categorie di film visualizzate dalla pagina master della visualizzazione. La chiave dei film rappresenta l'elenco dei film visualizzati dalla pagina Visualizzazione indice.
L'azione Details() aggiunge anche due chiavi denominate categorie e film. La chiave delle categorie, ancora una volta, rappresenta l'elenco delle categorie di film visualizzate dalla pagina master della visualizzazione. La chiave del film rappresenta l'elenco dei film in una determinata categoria visualizzata dalla pagina Visualizzazione dettagli (vedere la figura 2).
Figura 02: Visualizzazione dettagli (Fare clic per visualizzare l'immagine full-size)
La visualizzazione Indice è contenuta nell'elenco 2. Esegue semplicemente l'iterazione dell'elenco dei film rappresentati dall'elemento film in visualizzazione dati.
Presentazione 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>
La pagina master della visualizzazione è contenuta nell'elenco 3. La pagina master della visualizzazione esegue l'iterazione e esegue il rendering di tutte le categorie di film rappresentate dall'elemento categorie dai dati della visualizzazione.
Elenco 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>
Tutti i dati vengono passati alla visualizzazione e alla pagina master della visualizzazione tramite i dati di visualizzazione. Questo è il modo corretto per passare i dati alla pagina master.
Quindi, cosa c'è di sbagliato con questa soluzione? Il problema è che questa soluzione viola il principio DRY (Non ripetere te stesso). Ogni azione del controller deve aggiungere lo stesso elenco di categorie di film per visualizzare i dati. La presenza di codice duplicato nell'applicazione rende l'applicazione molto più difficile da gestire, adattare e modificare.
Soluzione valida
In questa sezione viene esaminata una soluzione alternativa e migliore per passare i dati da un'azione del controller a una pagina master di visualizzazione. Invece di aggiungere le categorie di film per la pagina master in ogni azione controller, si aggiungono le categorie di film ai dati di visualizzazione una sola volta. Tutti i dati di visualizzazione usati dalla pagina master di visualizzazione vengono aggiunti in un controller applicazione.
La classe ApplicationController è contenuta nell'elenco 4.
Elenco 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;
}
}
}
Esistono tre elementi da notare sul controller dell'applicazione nell'elenco 4. Prima di tutto, si noti che la classe eredita dalla classe Base System.Web.Mvc.Controller. Il controller applicazione è una classe controller.
In secondo luogo, si noti che la classe controller application è una classe astratta. Una classe astratta è una classe che deve essere implementata da una classe concreta. Poiché il controller applicazione è una classe astratta, non è possibile richiamare direttamente i metodi definiti nella classe. Se si tenta di richiamare direttamente la classe Application, verrà visualizzato un messaggio di errore Impossibile trovare una risorsa.
In terzo luogo, si noti che il controller applicazione contiene un costruttore che aggiunge l'elenco delle categorie di film per visualizzare i dati. Ogni classe controller che eredita dal controller applicazione chiama automaticamente il costruttore del controller applicazione. Ogni volta che si chiama un'azione su qualsiasi controller che eredita dal controller applicazione, le categorie di film vengono incluse automaticamente nei dati di visualizzazione.
Il controller Film in Elenco 5 eredita dal controller applicazione.
Elenco 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();
}
}
}
Il controller Movies, proprio come il controller Home illustrato nella sezione precedente, espone due metodi di azione denominati Index()
e Details()
. Si noti che l'elenco delle categorie di film visualizzate dalla pagina master della visualizzazione non viene aggiunto per visualizzare i dati nel Index()
metodo o Details()
. Poiché il controller Film eredita dal controller applicazione, l'elenco delle categorie di film viene aggiunto automaticamente per visualizzare i dati.
Si noti che questa soluzione per aggiungere i dati di visualizzazione per una pagina master di visualizzazione non viola il principio DRY (Non ripetere te stesso). Il codice per l'aggiunta dell'elenco delle categorie di film per visualizzare i dati è contenuto in una sola posizione: il costruttore per il controller applicazione.
Riepilogo
In questa esercitazione sono stati illustrati due approcci per passare i dati di visualizzazione da un controller a una pagina master di visualizzazione. In primo luogo, abbiamo esaminato un approccio semplice, ma difficile da mantenere. Nella prima sezione è stato illustrato come aggiungere dati di visualizzazione per una pagina master di visualizzazione in ogni azione controller nell'applicazione. Abbiamo concluso che questo era un approccio non valido perché viola il principio DRY (Non ripetere te stesso).
Successivamente, è stata esaminata una strategia molto migliore per l'aggiunta di dati richiesti da una pagina master di visualizzazione per visualizzare i dati. Anziché aggiungere i dati di visualizzazione in ogni azione e ogni azione del controller, sono stati aggiunti i dati di visualizzazione una sola volta all'interno di un controller applicazione. In questo modo, è possibile evitare codice duplicato quando si passano dati a una pagina master di visualizzazione in un'applicazione ASP.NET MVC.