Pasar datos a las páginas maestras de vista (VB)

por Microsoft

Descargar PDF

El objetivo de este tutorial es explicar cómo puede pasar datos de un controlador a una página maestra de vista. Se examinarán dos estrategias para pasar datos a una página maestra de vista. En primer lugar, se describe una solución sencilla que da lugar a una aplicación que es difícil de mantener. A continuación, se examina una solución mucho mejor que requiere un poco más de trabajo inicial, pero da como resultado una aplicación mucho más fácil de mantener.

Transferencia de datos a páginas maestras de vista

El objetivo de este tutorial es explicar cómo puede pasar datos de un controlador a una página maestra de vista. Se examinarán dos estrategias para pasar datos a una página maestra de vista. En primer lugar, se describe una solución sencilla que da lugar a una aplicación que es difícil de mantener. A continuación, se examina una solución mucho mejor que requiere un poco más de trabajo inicial, pero da como resultado una aplicación mucho más fácil de mantener.

El problema

Imagine que va a compilar una aplicación de base de datos de películas y quiere mostrar la lista de categorías de películas en cada página de la aplicación (vea la figura 1). Imagine, además, que la lista de categorías de películas se almacena en una tabla de base de datos. En ese caso, tendría sentido recuperar las categorías de la base de datos y representar la lista de categorías de películas dentro de una página maestra de vista.

Displaying movie categories in a view master page

Figura 01: Presentación de categorías de películas en una página maestra de vista (haga clic para ver la imagen en tamaño completo)

Este es el problema. ¿Cómo se recupera la lista de categorías de películas en la página maestra? Es tentador llamar directamente a los métodos de sus clases de modelo directamente en la página maestra. Es decir, es tentador incluir el código para recuperar los datos de la base de datos directamente en la página maestra. Pero si omite los controladores de MVC para acceder a la base de datos infringiría la separación correcta de intereses, que es una de las principales ventajas de compilar una aplicación MVC.

En una aplicación MVC, quiere que los controladores de MVC controlen toda la interacción entre las vistas y el modelo de MVC. Esta separación de intereses da como resultado una aplicación más fácil de mantener, adaptar y probar.

En una aplicación MVC, todos los datos que se pasen a una vista (incluida una página maestra de vista) se deben pasar mediante una acción del controlador. Además, los datos se deben pasar aprovechando los datos de vista. En el resto de este tutorial, se examinarán dos métodos para pasar datos de vista a una página maestra de vista.

La solución sencilla

Vamos a comenzar con la solución más sencilla para pasar datos de vista de un controlador a una página maestra de vista. La solución más sencilla consiste en pasar los datos de vista de la página maestra en todas y cada una de las acciones del controlador.

Examinemos el controlador de la lista 1. Expone dos acciones denominadas Index() y Details(). El método de acción Index() devuelve todas las películas de la tabla de base de datos Películas. El método de acción Details() devuelve todas las películas de una categoría de películas determinada.

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

Observe que las acciones Index() y Details() agregan dos elementos para ver los datos. La acción Index()agrega dos claves: categorías y películas. La clave categorías representa la lista de categorías de películas que se muestran en la página maestra de vista. La clave películas representa la lista de películas que se muestran en la página de vista de índice.

La acción Details() también agrega dos claves denominadas categorías y películas. De nuevo, la clave categorías representa la lista de categorías de películas que se muestran en la página maestra de vista. La clave películas representa la lista de películas de una categoría determinada que se muestra en la página de vista de detalles (vea la figura 2).

The Details view

Figura 02: La vista Detalles (Haga clic para ver la imagen en tamaño completo)

La vista Índice se muestra en la lista 2. Simplemente itera a través de la lista de películas representadas por el elemento películas en los datos de vista.

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>

La página maestra de vista se muestra en la lista 3. La página maestra de vista itera y representa todas las categorías de películas representadas por el elemento categorías de los datos de vista.

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>

Todos los datos se pasan a la vista y a la página maestra de vista mediante datos de vista. Es la manera correcta de pasar datos a la página maestra.

Por tanto, ¿cuál es el problema de esta solución? El problema es que esta solución infringe el principio DRY (Una vez y solo una). Todas y cada una de las acciones del controlador deben agregar la misma lista de categorías de películas a los datos de vista. Tener código duplicado en la aplicación hace que sea mucho más difícil de mantener, adaptar y modificar.

La solución correcta

En esta sección, se estudia una solución alternativa y mejor para pasar datos de una acción del controlador a una página maestra de vista. En lugar de agregar las categorías de películas para la página maestra en todas y cada una de las acciones del controlador, solo se agregan una vez las categorías de películas a los datos de vista. Todos los datos de vista que use la página maestra de vista se agregan en un controlador Aplicación.

La clase de ApplicationController se muestra en la lista 4.

La clase de ApplicationController se muestra en la lista 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

Hay tres aspectos que debe tener en cuenta sobre el controlador Aplicación de la lista 4. En primer lugar, observe que la clase hereda de la clase base System.Web.Mvc.Controller. El controlador Aplicación es una clase de controlador.

En segundo lugar, observe que la clase del controlador Aplicación es una clase de MustInherit. Una clase de MustInherit es la que se debe implementar mediante una clase concreta. Como el controlador Aplicación es una clase de MustInherit, no puede invocar ningún método definido en la clase directamente. Si intenta invocar la clase Aplicación directamente, recibirá un mensaje de error Resource Cannot Be Found (No se puede encontrar el recurso).

En tercer lugar, observe que el controlador Aplicación contiene un constructor que agrega la lista de categorías de películas a los datos de vista. Todas las clases del controlador que heredan del controlador Aplicación llaman automáticamente al constructor del controlador Aplicación. Siempre que llame a alguna acción en cualquier controlador que herede del controlador Aplicación, las categorías de películas se incluyen automáticamente en los datos de vista.

El controlador Películas de la lista 5 hereda del controlador Aplicación.

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

El controlador Películas, al igual que el controlador Inicio descrito en la sección anterior, expone dos métodos de acción denominados Index() y Details(). Observe que la lista de categorías de películas que se muestra en la página maestra de vista no se agrega a los datos de vista en el método Index() ni en el Details(). Como el controlador Películas hereda del controlador Aplicación, la lista de categorías de películas se agrega automáticamente a los datos de vista.

Tenga en cuenta que esta solución de agregar datos de vista de una página maestra de vista no infringe el principio DRY (Una vez y solo una). El código para agregar la lista de categorías de películas a los datos de vista solo se encuentra en una ubicación: el constructor del controlador Aplicación.

Resumen

En este tutorial, se han analizado dos enfoques para pasar datos de vista de un controlador a una página maestra de vista. En primer lugar, se ha analizado un enfoque sencillo pero difícil de mantener. En la primera sección, se ha explicado cómo puede agregar datos de vista de una página maestra de vista en todas y cada una de las acciones del controlador de la aplicación. Se ha concluido que era un enfoque incorrecto porque infringe el principio DRY (Una vez y solo una).

A continuación, se ha analizado una estrategia mucho mejor para agregar los datos que requiera una página maestra de vista a los datos de vista. En lugar de agregar los datos de vista en todas y cada una de las acciones del controlador, solo se agregan una vez dentro de un controlador Aplicación. De este modo, puede evitar el código duplicado al pasar datos a una página maestra de vista en una aplicación ASP.NET MVC.