Inserción de dependencias de ASP.NET MVC 4

por el equipo de Web Camps

Descarga del kit de formación de Web Camps

En este laboratorio práctico se asume que tiene conocimientos básicos de ASP.NET MVC y filtros de ASP.NET MVC 4. Si no ha usado filtros de ASP.NET MVC 4 antes, le recomendamos que vaya al laboratorio práctico Filtros de acción personalizada de ASP.NET MVC.

Nota:

Todos los fragmentos de código y el código de ejemplo se incluyen en el Kit de entrenamiento de Web Camps, disponible en Microsoft-Web/WebCampTrainingKit Releases. El proyecto específico de este laboratorio está disponible en Inserción de dependencias de ASP.NET MVC 4.

En el paradigma de programación orientada a objetos, los objetos funcionan juntos en un modelo de colaboración donde hay colaboradores y consumidores. Naturalmente, este modelo de comunicación genera dependencias entre objetos y componentes, lo que resulta difícil de administrar cuando aumenta la complejidad.

Class dependencies and model complexity

Dependencias de clase y complejidad del modelo

Probablemente haya oído hablar del patrón de fábrica y la separación entre la interfaz y la implementación mediante servicios, donde los objetos de cliente suelen ser responsables de la ubicación del servicio.

El patrón de inserción de dependencias es una implementación concreta de inversión de control. La inversión de control (IoC) significa que los objetos no crean otros objetos en los que se basan para realizar su trabajo. En su lugar, obtienen los objetos que necesitan de un origen externo (por ejemplo, un archivo de configuración xml).

La inserción de dependencias (DI) significa que esto se realiza sin la intervención del objeto, normalmente mediante un componente de marco que pasa parámetros de constructor y establece propiedades.

Patrón de diseño de inserción de dependencias (DI)

En un nivel alto, el objetivo de la inserción de dependencias es que una clase de cliente (por ejemplo, el golfista) necesita algo que satisfaga una interfaz (por ejemplo, IClub). No importa cuál es el tipo concreto (por ejemplo WoodClub, IronClub, WedgeClub o PutterClub), quiere que alguien más lo controle (por ejemplo, un buen caddie). El Solucionador de dependencias de ASP.NET MVC puede permitirle registrar la lógica de dependencias en otro lugar (por ejemplo, un contenedor o una bolsa de palos).

Dependency Injection diagram

Inserción de dependencias: Analogía de golf

Las ventajas de usar el patrón de inserción de dependencias y la inversión de control son las siguientes:

  • Reduce el acoplamiento de clases
  • Aumenta la reutilización de código
  • Mejora la capacidad de mantenimiento del código
  • Mejora las pruebas de aplicaciones

Nota:

La inserción de dependencias a veces se compara con el patrón de diseño de fábrica abstracta, pero hay una ligera diferencia entre ambos enfoques. La inserción de dependencias tiene un marco de trabajo subyacente para resolver las dependencias mediante una llamada a los generadores y los servicios registrados.

Ahora que comprende el patrón de inserción de dependencias, aprenderá a lo largo de este laboratorio cómo aplicarlo en ASP.NET MVC 4. Comenzará a usar la inserción de dependencias en los Controladores para incluir un servicio de acceso a la base de datos. A continuación, aplicará la inserción de dependencias a las Vistas para consumir un servicio y mostrar información. Por último, extenderá la inserción de dependencias a filtros de ASP.NET MVC 4, insertando un filtro de acción personalizado en la solución.

En este laboratorio práctico, aprenderá a:

  • Integración de ASP.NET MVC 4 con Unity para la inserción de dependencias mediante paquetes NuGet
  • Uso de la inserción de dependencias dentro de un controlador MVC de ASP.NET
  • Uso de la inserción de dependencias dentro de una vista MVC de ASP.NET
  • Usar la inserción de dependencias dentro de un filtro de acción MVC de ASP.NET

Nota:

Este laboratorio usa el paquete NuGet Unity.Mvc3 para la resolución de dependencias, pero es posible adaptar cualquier marco de inserción de dependencias para trabajar con ASP.NET MVC 4.

Requisitos previos

Debe tener los siguientes elementos para completar este laboratorio:

Configuración

Instalación de fragmentos de código

Para mayor comodidad, gran parte del código que va a administrar a lo largo de este laboratorio está disponible como fragmentos de código de Visual Studio. Para instalar los fragmentos de código, ejecute archivo.\Source\Setup\CodeSnippets.vsi.

Si no está familiarizado con los fragmentos de código de Visual Studio Code y quiere obtener información sobre cómo usarlos, puede consultar el apéndice de este documento "Apéndice B: Usar fragmentos de código".


Ejercicios

Este laboratorio práctico está compuesto por los siguientes ejercicios:

  1. Ejercicio 1: Inserción de un controlador
  2. Ejercicio 2: Inserción de una vista
  3. Ejercicio 3: Inserción de filtros

Nota:

Cada ejercicio va acompañado de una carpeta End que contiene la solución resultante que debe obtener después de completar los ejercicios. Puede usar esta solución como guía si necesita ayuda adicional para trabajar con los ejercicios.

Tiempo estimado para completar este laboratorio: 30 minutos.

Ejercicio 1: Inserción de un controlador

En este ejercicio, aprenderá a usar la inserción de dependencias en controladores ASP.NET MVC mediante la integración de Unity mediante un paquete NuGet. Por ese motivo, incluirá servicios en los controladores de MvcMusicStore para separar la lógica del acceso a los datos. Los servicios crearán una nueva dependencia en el constructor del controlador, que se resolverá mediante la inserción de dependencias con la ayuda de Unity.

Este enfoque le mostrará cómo generar aplicaciones menos acopladas, que son más flexibles y fáciles de mantener y probar. También aprenderá a integrar ASP.NET MVC con Unity.

Acerca del servicio StoreManager

La tienda de música MVC proporcionada en la solución Begin ahora incluye un servicio que administra los datos del controlador de la tienda denominado StoreService. A continuación encontrará la implementación del Servicio de tienda. Tenga en cuenta que todos los métodos devuelven entidades Model.

namespace MvcMusicStore.Controllers
{    
    using System.Web.Mvc;
    using MvcMusicStore.Filters;
    using MvcMusicStore.Services;

    [MyNewCustomActionFilter(Order = 1)]
    [CustomActionFilter(Order = 2)]
    public class StoreController : Controller
    {
        private IStoreService service;

        public StoreController(IStoreService service)
        {
            this.service = service;
        }

        // GET: /Store/
        public ActionResult Details(int id)
        {
            var album = this.service.GetAlbum(id);
            if (album == null)
            {
                return this.HttpNotFound();
            }

            return this.View(album);
        }

        public ActionResult Browse(string genre)
        {
            // Retrieve Genre and its Associated Albums from database
            var genreModel = this.service.GetGenreByName(genre);

            return this.View(genreModel);
        }

        public ActionResult Index()
        {
            var genres = this.service.GetGenres();

            return this.View(genres);
        }

        // GET: /Store/GenreMenu
        public ActionResult GenreMenu()
        {
            var genres = this.service.GetGenres();

            return this.PartialView(genres);
        }
    }
}

StoreController desde la solución Begin ahora consume StoreService. Todas las referencias de datos se quitaron de StoreController y ahora es posible modificar el proveedor de acceso a datos actual sin cambiar ningún método que consuma StoreService.

A continuación, verá que la implementación de StoreController tiene una dependencia con StoreService dentro del constructor de clase.

Nota:

La dependencia introducida en este ejercicio está relacionada con la inversión de control (IoC).

El constructor de clase StoreController recibe un parámetro de tipo IStoreService, que es esencial para realizar llamadas de servicio desde dentro de la clase. Sin embargo, StoreController no implementa el constructor predeterminado (sin parámetros) que cualquier controlador debe tener para trabajar con ASP.NET MVC.

Para resolver la dependencia, un generador abstracto debe crear el controlador (una clase que devuelve cualquier objeto del tipo especificado).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.ViewModels;
using MvcMusicStore.Models;
using MvcMusicStore.Services;

namespace MvcMusicStore.Controllers
{
    public class StoreController : Controller
    {
        private IStoreService service;

        public StoreController(IStoreService service)
        {
            this.service = service;
        }

        //
        // GET: /Store/
        public ActionResult Index()
        {
            // Create list of genres
            var genres = this.service.GetGenreNames();

            // Create your view model
            var viewModel = new StoreIndexViewModel
            {
                Genres = genres.ToList(),
                NumberOfGenres = genres.Count()
            };

            return View(viewModel);
        }

        //
        // GET: /Store/Browse?genre=Disco
        public ActionResult Browse(string genre)
        {
            var genreModel = this.service.GetGenreByName(genre);

            var viewModel = new StoreBrowseViewModel()
            {
                Genre = genreModel,
                Albums = genreModel.Albums.ToList()
            };

            return View(viewModel);
        }

        //
        // GET: /Store/Details/5
        public ActionResult Details(int id)
        {
            var album = this.service.GetAlbum(id);

            return View(album);
        }
    }
}

Nota:

Recibirá un error cuando la clase intente crear StoreController sin enviar el objeto de servicio, ya que no hay ningún constructor sin parámetros declarado.

Tarea 1: Ejecución de la aplicación

En esta tarea, ejecutará la aplicación Begin, que incluye el servicio en el controlador de la tienda que separa el acceso a los datos de la lógica de la aplicación.

Al ejecutar la aplicación, recibirá una excepción, ya que el servicio de controlador no se pasa como parámetro de forma predeterminada:

  1. Abra la solución Begin ubicada en Source\Ex01-Injecting Controller\Begin.

    1. Tendrá que descargar algunos paquetes NuGet que faltan antes de continuar. Para ello, haga clic en el menú Proyecto y seleccione Administrar paquetes NuGet.

    2. En el cuadro de diálogo Administrar paquetes NuGet, haga clic en Restaurar para descargar los paquetes que faltan.

    3. Por último, para compilar la solución, haga clic en Compilar | solución de compilación.

      Nota:

      Una de las ventajas de usar NuGet es que no es necesario enviar todas las bibliotecas del proyecto, lo que reduce el tamaño del proyecto. Con NuGet Power Tools, especificando las versiones del paquete en el archivo Packages.config, podrá descargar todas las bibliotecas necesarias la primera vez que ejecute el proyecto. Por ello, tendrá que ejecutar estos pasos después de abrir una solución existente de este laboratorio.

  2. Presione Ctrl + F5 para ejecutar la aplicación sin depurar. Recibirá el mensaje de error "No se ha definido ningún constructor sin parámetros para este objeto":

    Error while running ASP.NET MVC Begin Application

    Error al ejecutar la aplicación Begin de ASP.NET MVC

  3. Cierre el explorador.

En los pasos siguientes, trabajará en la solución Music Store para insertar la dependencia que necesita este controlador.

Tarea 2: Inclusión de Unity en la solución MvcMusicStore

En esta tarea, incluirá el paquete NuGet Unity.Mvc3 en la solución.

Nota:

El paquete Unity.Mvc3 se diseñó para ASP.NET MVC 3, pero es totalmente compatible con ASP.NET MVC 4.

Unity es un contenedor ligero y extensible de inserción de dependencias con compatibilidad opcional para la interceptación de tipos y instancias. Es un contenedor de uso general para su uso en cualquier tipo de aplicación .NET. Proporciona todas las características comunes que se encuentran en los mecanismos de inserción de dependencias, como la creación de objetos, la abstracción de los requisitos especificando dependencias en tiempo de ejecución y flexibilidad, aplazando la configuración del componente al contenedor.

  1. Instale el paquete NuGet Unity.Mvc3 en el proyecto MvcMusicStore. Para ello, abra la Consola del administrador de paquetes desde Ver | Otras ventanas.

  2. Ejecute el siguiente comando:

    PMC

    Install-Package Unity.Mvc3
    

    Installing Unity.Mvc3 NuGet Package

    Instalación del paquete NuGet Unity.Mvc3

  3. Una vez instalado el paquete Unity.Mvc3, explore los archivos y carpetas que agrega automáticamente para simplificar la configuración de Unity.

    Unity.Mvc3 package installed

    Paquete Unity.Mvc3 instalado

Tarea 3: Registro de Unity en Global.asax.cs Application_Start

En esta tarea, actualizará el método Application_Start ubicado en Global.asax.cs para llamar al inicializador de arranque de Unity y, a continuación, actualizará el archivo Bootstrapper que registra el servicio y el controlador que usará para la inserción de dependencias.

  1. Ahora, enlazará el programa previo que es el archivo que inicializa el contenedor de Unity y el solucionador de dependencias. Para ello, abra Global.asax.cs y agregue el código resaltado siguiente dentro del método Application_Start.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej01 - Inicializar Unity)

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
    
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    
        Bootstrapper.Initialise();
    
        AppConfig.Configure();
    }
    
  2. Abra el archivo Bootstrapper.cs.

  3. Incluya los siguientes espacios de nombres: MvcMusicStore.Services y MusicStore.Controllers.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej01 - Programa de arranque para agregar espacios de nombres)

    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    using Unity.Mvc3;
    using MvcMusicStore.Services;
    using MvcMusicStore.Controllers;
    
  4. Reemplace el contenido del método BuildUnityContainer por el código siguiente que registra el controlador de la tienda y el servicio de almacenamiento.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej01 - Registro del controlador de almacén y servicio)

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
    
        container.RegisterType<IStoreService, StoreService>();
        container.RegisterType<IController, StoreController>("Store");
    
        return container;
    }
    

Tarea 4: Ejecución de la aplicación

En esta tarea, ejecutará la aplicación para comprobar que ahora se puede cargar después de incluir Unity.

  1. Presione F5 para ejecutar la aplicación; la aplicación ahora debe cargarse sin mostrar ningún mensaje de error.

    Running Application with Dependency Injection

    Ejecución de la aplicación con inserción de dependencias

  2. Vaya a /Store. Esto invocará StoreController, que ahora se crea con Unity.

    MVC Music Store

    MVC Music Store

  3. Cierre el explorador.

En los ejercicios siguientes aprenderá a ampliar el ámbito de inserción de dependencias para usarlo dentro de vistas de ASP.NET MVC y filtros de acción.

Ejercicio 2: Inserción de una vista

En este ejercicio, aprenderá a usar la inserción de dependencias en una vista con las nuevas características de integración para Unity de ASP.NET MVC 4. Para ello, llamará a un servicio personalizado dentro de la vista Examinar de la Tienda, que mostrará un mensaje y una imagen a continuación.

A continuación, integrará el proyecto con Unity y creará una resolución de dependencias personalizada para insertar las dependencias.

Tarea 1: Creación de una vista que consume un servicio

En esta tarea, creará una vista que realiza una llamada de servicio para generar una nueva dependencia. El servicio consta de un servicio de mensajería simple incluido en esta solución.

  1. Abra la solución Begin ubicada en la carpeta Source\Ex02-Injecting View\Begin. De lo contrario, puede seguir utilizando la solución Final obtenida al completar el ejercicio anterior.

    1. Si abrió la solución Begin proporcionada, deberá descargar algunos paquetes NuGet que faltan antes de continuar. Para ello, haga clic en el menú Proyecto y seleccione Administrar paquetes NuGet.

    2. En el cuadro de diálogo Administrar paquetes NuGet, haga clic en Restaurar para descargar los paquetes que faltan.

    3. Por último, para compilar la solución, haga clic en Compilar | solución de compilación.

      Nota:

      Una de las ventajas de usar NuGet es que no es necesario enviar todas las bibliotecas del proyecto, lo que reduce el tamaño del proyecto. Con NuGet Power Tools, especificando las versiones del paquete en el archivo Packages.config, podrá descargar todas las bibliotecas necesarias la primera vez que ejecute el proyecto. Por ello, tendrá que ejecutar estos pasos después de abrir una solución existente de este laboratorio.

      Para obtener más información, vea este artículo: https://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages.

  2. Incluya las clases de MessageService.cs yIMessageService.cs ubicadas en la carpeta Source \Assets en /Services. Para ello, haga clic con el botón derecho en la carpeta Services y seleccione Agregar elemento existente. Vaya a la ubicación de los archivos e inclúyalos.

    Adding Message Service and Service Interface

    Adición del servicio de mensajes y la interfaz de servicio

    Nota:

    La interfaz IMessageService define dos propiedades implementadas por la clase MessageService. Estas propiedades, Message e ImageUrl, almacenan el mensaje y la dirección URL de la imagen que se va a mostrar.

  3. Cree la carpeta /Pages en la carpeta raíz del proyecto y agregue la clase existente MyBasePage.cs desde Source\Assets. La página base de la que heredará tiene la siguiente estructura.

    Pages folder

    namespace MvcMusicStore.Pages
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using Microsoft.Practices.Unity;
        using MvcMusicStore.Models;
        using MvcMusicStore.Services;
    
        public class MyBasePage : System.Web.Mvc.WebViewPage<Genre>
        {
            [Dependency]
            public IMessageService MessageService { get; set; }
    
            public override void 
    
            Execute()
            {
            }
        }
    }
    
  4. Abra la vista Browse.cshtml desde la carpeta /Views/Store y haga que herede de MyBasePage.cs.

    @inherits MvcMusicStore.Pages.MyBasePage
    @{
         ViewBag.Title = "Browse Albums";
    }
    
  5. En la vista Examinar, agregue una llamada a MessageService para mostrar una imagen y un mensaje recuperado por el servicio. (C#)

    @inherits MvcMusicStore.Pages.MyBasePage    
    @{
        Viewbag.Title = "Browse Albums";
    }
    <div>
        @this.MessageService.Message
        <br />
        <img alt="@this.MessageService.Message" src="@this.MessageService.ImageUrl" />
    </div>
    ...
    

Tarea 2: Inclusión de un solucionador de dependencias personalizado y un activador de página de vista personalizado

En la tarea anterior, insertó una nueva dependencia dentro de una vista para realizar una llamada de servicio dentro de ella. Ahora, resolverá esa dependencia mediante la implementación de las interfaces de inserción de dependencias de ASP.NET MVC IViewPageActivator e IDependencyResolver. Incluirá en la solución una implementación de IDependencyResolver que tratará la recuperación del servicio mediante Unity. A continuación, incluirá otra implementación personalizada de la interfaz IViewPageActivator que resolverá la creación de las vistas.

Nota:

Desde ASP.NET MVC 3, la implementación de inserción de dependencias ha simplificado las interfaces para registrar los servicios. IDependencyResolver e IViewPageActivator forman parte de las características de ASP.NET MVC 3 para la inserción de dependencias.

La interfaz IDependencyResolver reemplaza al IMvcServiceLocator anterior. Los implementadores de IDependencyResolver deben devolver una instancia del servicio o una colección de servicios.

public interface IDependencyResolver {
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

La interfaz IViewPageActivator proporciona un control más específico sobre cómo se crean instancias de las páginas de vista a través de la inserción de dependencias. Las clases que implementan la interfaz IViewPageActivator pueden crear instancias de vista mediante información de contexto.

public interface IViewPageActivator {
    object Create(ControllerContext controllerContext, Type type);
}
  1. Cree la carpeta /Factories en la carpeta raíz del proyecto.

  2. Incluya CustomViewPageActivator.cs a la solución desde la carpeta /Sources/Assets/ a Factories. Para ello, haga clic con el botón derecho en la carpeta /Factories, seleccione Agregar | Elemento existente y, a continuación, seleccione CustomViewPageActivator.cs. Esta clase implementa la interfaz IViewPageActivator para contener el contenedor de Unity.

    namespace MvcMusicStore.Factories
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Web.Mvc;
        using Microsoft.Practices.Unity;
    
        public class CustomViewPageActivator : IViewPageActivator
        {
            private IUnityContainer container;
    
            public CustomViewPageActivator(IUnityContainer container)
            {
                this.container = container;
            }
    
            public object Create(ControllerContext controllerContext, Type type)
            {
                return this.container.Resolve(type);
            }
        }
    }
    

    Nota:

    CustomViewPageActivator es responsable de administrar la creación de una vista mediante un contenedor de Unity.

  3. Incluya el archivo UnityDependencyResolver.cs de /Sources/Assets a la carpeta /Factories. Para ello, haga clic con el botón derecho en la carpeta /Factories, seleccione Agregar | Elemento existente y, a continuación, seleccione el archivo UnityDependencyResolver.cs.

    namespace MvcMusicStore.Factories
    {
         using System;
         using System.Collections.Generic;
         using System.Linq;
         using System.Web;
         using System.Web.Mvc;
         using Microsoft.Practices.Unity;
    
         public class UnityDependencyResolver : IDependencyResolver
         {
              private IUnityContainer container;
    
              private IDependencyResolver resolver;
    
              public UnityDependencyResolver(IUnityContainer container, IDependencyResolver resolver)
              {
                    this.container = container;
                    this.resolver = resolver;
              }
    
              public object GetService(Type serviceType)
              {
                    try
                    {
                         return this.container.Resolve(serviceType);
                    }
                    catch
                    {
                         return this.resolver.GetService(serviceType);
                    }
              }
    
              public IEnumerable<object> GetServices(Type serviceType)
              {
                    try
                    {
                         return this.container.ResolveAll(serviceType);
                    }
                    catch
                    {
                         return this.resolver.GetServices(serviceType);
                    }
              }
         }
    }
    

    Nota:

    La clase UnityDependencyResolver es un DependencyResolver personalizado para Unity. Cuando no se encuentra un servicio dentro del contenedor de Unity, se invoca la resolución base.

En la tarea siguiente, ambas implementaciones se registrarán para que el modelo conozca la ubicación de los servicios y las vistas.

Tarea 3: Registro para la inserción de dependencias en el contenedor de Unity

En esta tarea, combinará todo lo anterior para que funcione la inserción de dependencias.

Hasta ahora, la solución tiene los siguientes elementos:

  • Una vista Browse que hereda de MyBaseClass y consume MessageService.
  • Una clase intermedia, MyBaseClass, que tiene la inserción de dependencias declarada para la interfaz de servicio.
  • Un servicio, MessageService, y su interfaz IMessageService.
  • Un solucionador de dependencias personalizado de Unity: UnityDependencyResolver, que se ocupa de la recuperación del servicio.
  • Un activador de página de vista , CustomViewPageActivator, que crea la página.

Para insertar la vista Browse, ahora registrará la resolución de dependencias personalizada en el contenedor de Unity.

  1. Abra el archivo Bootstrapper.cs.

  2. Registre una instancia de MessageService en el contenedor de Unity para inicializar el servicio:

    (Fragmento de código: Laboratorio de inserción de dependencias ASP.NET - Ej02 - Registro del servicio de mensajes)

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
    
        container.RegisterType<IStoreService, StoreService>();
        container.RegisterType<IController, StoreController>("Store");
    
        container.RegisterInstance<IMessageService>(new MessageService
        {
            Message = "You are welcome to our Web Camps Training Kit!",
            ImageUrl = "/Content/Images/webcamps.png"
        });
        //...
    }
    
  3. Agregue una referencia al espacio de nombres MvcMusicStore.Factorys.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej02 - Espacio de nombres de Factories)

    using System.Web.Mvc; 
    using Microsoft.Practices.Unity; 
    using Unity.Mvc3; 
    using MvcMusicStore.Services; 
    using MvcMusicStore.Controllers; 
    using MvcMusicStore.Factories;
    
  4. Registre CustomViewPageActivator como activador de página de vista en el contenedor de Unity:

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej02 - Registro de CustomViewPageActivator)

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
    
        container.RegisterType<IStoreService, StoreService>();
        container.RegisterType<IController, StoreController>("Store");
    
        container.RegisterInstance<IMessageService>(new MessageService
        {
            Message = "You are welcome to our Web Camps Training Kit!",
            ImageUrl = "/Content/Images/webcamps.png"
        });
    
        container.RegisterType<IViewPageActivator, CustomViewPageActivator>(new InjectionConstructor(container));
    
        return container;
    }
    
  5. Reemplace el solucionador de dependencias predeterminado de ASP.NET MVC 4 por una instancia de UnityDependencyResolver. Para ello, reemplace el contenido del método Initialize por el código siguiente:

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej02 - Actualización del solucionador de dependencias)

    public static void Initialise()
    {
        var container = BuildUnityContainer();
    
        DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
    
        IDependencyResolver resolver = DependencyResolver.Current;
    
        IDependencyResolver newResolver = new Factories.UnityDependencyResolver(container, resolver);
    
        DependencyResolver.SetResolver(newResolver);
    }
    

    Nota:

    ASP.NET MVC proporciona una clase de resolución de dependencias predeterminada. Para trabajar con solucionadores de dependencias personalizados como el que hemos creado para Unity, este solucionador debe reemplazarse.

Tarea 4: Ejecución de la aplicación

En esta tarea, ejecutará la aplicación para comprobar que el Explorador de la Tienda consume el servicio y muestra la imagen y el mensaje recuperado:

  1. Presione F5 para ejecutar la aplicación.

  2. Haga clic en Rock en el menú Géneros y vea cómo se insertó MessageService en la vista y cargó el mensaje de bienvenida y la imagen. En este ejemplo, vamos a escribir en "Rock":

    MVC Music Store - View Injection

    Tienda de música de MVC: Visualización de inserción

  3. Cierre el explorador.

Ejercicio 3: Inserción de filtros de acción

En los filtros de acción personalizados del laboratorio práctico anteriores, ha trabajado con la personalización e inserción de filtros. En este ejercicio, aprenderá a insertar filtros con inserción de dependencias mediante el contenedor de Unity. Para ello, agregará a la solución de Tienda de Música un filtro de acción personalizado que rastreará la actividad del sitio.

Tarea 1: Inclusión del filtro de seguimiento en la solución

En esta tarea, incluirá en la Tienda de Música un filtro de acción personalizado para realizar el seguimiento de eventos. Como los conceptos del filtro de acciones personalizados ya se tratan en el laboratorio anterior "Filtros de acciones personalizadas", simplemente incluirá la clase de filtro de la carpeta Assets de este laboratorio y, a continuación, creará un proveedor de filtros para Unity:

  1. Abra la solución Begin ubicada en la carpeta Source\Ex03 - Inserting Action Filter\Begin. De lo contrario, puede seguir utilizando la solución Final obtenida al completar el ejercicio anterior.

    1. Si abrió la solución Begin proporcionada, deberá descargar algunos paquetes NuGet que faltan antes de continuar. Para ello, haga clic en el menú Proyecto y seleccione Administrar paquetes NuGet.

    2. En el cuadro de diálogo Administrar paquetes NuGet, haga clic en Restaurar para descargar los paquetes que faltan.

    3. Por último, para compilar la solución, haga clic en Compilar | solución de compilación.

      Nota:

      Una de las ventajas de usar NuGet es que no es necesario enviar todas las bibliotecas del proyecto, lo que reduce el tamaño del proyecto. Con NuGet Power Tools, especificando las versiones del paquete en el archivo Packages.config, podrá descargar todas las bibliotecas necesarias la primera vez que ejecute el proyecto. Por ello, tendrá que ejecutar estos pasos después de abrir una solución existente de este laboratorio.

      Para obtener más información, vea este artículo: https://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages.

  2. Incluya el archivo TraceActionFilter.cs de /Sources/Assets a la carpeta /Filters.

    namespace MvcMusicStore.Filters
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Web.Mvc;
    
        public class TraceActionFilter : IActionFilter
        {
            public void OnActionExecuted(ActionExecutedContext filterContext)
            {
                filterContext.HttpContext.Trace.Write("OnActionExecuted");
                filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
                filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
            }
    
            public void OnActionExecuting(ActionExecutingContext filterContext)
            {
                filterContext.HttpContext.Trace.Write("OnActionExecuting");
                filterContext.HttpContext.Trace.Write("Action " + filterContext.ActionDescriptor.ActionName);
                filterContext.HttpContext.Trace.Write("Controller " + filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
            }
        }
    }
    

    Nota:

    Este filtro de acción personalizado realiza el seguimiento de ASP.NET. Puede comprobar el laboratorio de "Filtros de acción dinámicos y locales de ASP.NET MVC 4" para obtener más referencias.

  3. Agregue la clase vacía FilterProvider.cs al proyecto en la carpeta /Filters.

  4. Agregue los espacios de nombres System.Web.Mvc y Microsoft.Practices.Unity en FilterProvider.cs.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej03 - Proveedor de filtros que agrega espacios de nombres)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    
    namespace MvcMusicStore.Filters
    {
         public class FilterProvider
         {
         }
    }
    
  5. Haga que la clase herede de la interfaz IFilterProvider.

    namespace MvcMusicStore.Filters
    {
        public class FilterProvider : IFilterProvider
        {
        }
    }
    
  6. Agregue una propiedad IUnityContainer en la clase FilterProvider y, a continuación, cree un constructor de clase para asignar el contenedor.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej03 - Constructor del proveedor de filtros)

    public class FilterProvider : IFilterProvider
    {
        private IUnityContainer container;
    
        public FilterProvider(IUnityContainer container)
        {
            this.container = container;
        }
    }
    

    Nota:

    El constructor de clase de proveedor de filtros no está creando un nuevo objeto dentro. El contenedor se pasa como parámetro y Unity resuelve la dependencia.

  7. En la clase FilterProvider, implemente el método GetFilters desde la interfaz IFilterProvider.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej03 - Proveedor de filtros GetFilters)

    public class FilterProvider : IFilterProvider
    {
        private IUnityContainer container;
    
        public FilterProvider(IUnityContainer container)
        {
            this.container = container;
        }
    
        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            foreach (IActionFilter actionFilter in this.container.ResolveAll<IActionFilter>())
            {
                yield return new Filter(actionFilter, FilterScope.First, null);
            }
        }
    }
    

Tarea 2: Registro y habilitación del filtro

En esta tarea, habilitará el seguimiento del sitio. Para ello, registrará el filtro en el método Bootstrapper.cs BuildUnityContainer para iniciar el seguimiento:

  1. Abra Web.config ubicado en la raíz del proyecto y habilite el seguimiento de supervisión en el grupo System.Web.

    <system.web>
        <trace enabled="true"/>
        <compilation debug="true" targetFramework="4.5">
    
  2. Abra Bootstrapper.cs en la raíz del proyecto.

  3. Agregue una referencia al espacio de nombres MvcMusicStore.Filters.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej03 - Programa de arranque para agregar espacios de nombres)

    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    using Unity.Mvc3;
    using MvcMusicStore.Services;
    using MvcMusicStore.Controllers;
    using MvcMusicStore.Factories;
    using MvcMusicStore.Filters;
    
  4. Seleccione el método BuildUnityContainer y registre el filtro en el contenedor de Unity. Tendrá que registrar el proveedor de filtros, así como el filtro de acciones.

    (Fragmento de código: Laboratorio de inserción de dependencias de ASP.NET - Ej03 - Registro de FilterProvider y ActionFilter)

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
    
        //...
    
        container.RegisterInstance<IFilterProvider>("FilterProvider", new FilterProvider(container));
        container.RegisterInstance<IActionFilter>("LogActionFilter", new TraceActionFilter());
    
        return container;
    }
    

Tarea 3: Ejecución de la aplicación

En esta tarea, ejecutará la aplicación y probará que el filtro de acción personalizado está rastreando la actividad:

  1. Presione F5 para ejecutar la aplicación.

  2. Haga clic en Rock en el menú Géneros. Puede ir a más géneros si quiere.

    Music Store

    Tienda de música

  3. Vaya a /Trace.axd para ver la página Seguimiento de la aplicación y, a continuación, haga clic en Ver detalles.

    Application Trace Log

    Registro de seguimiento de aplicaciones

    Application Trace - Request Details

    Seguimiento de aplicaciones: detalles de la solicitud

  4. Cierre el explorador.


Resumen

Al completar este laboratorio práctico, ha aprendido a usar la inserción de dependencias en ASP.NET MVC 4 mediante la integración de Unity con un paquete NuGet. Para lograrlo, ha usado la inserción de dependencias dentro de controladores, vistas y filtros de acción.

Se trataron los siguientes conceptos:

  • Características de inserción de dependencias de ASP.NET MVC 4
  • Integración de Unity con el paquete NuGet Unity.Mvc3
  • Inserción de dependencias en controladores
  • Inserción de dependencias en vistas
  • Inserción de dependencias de filtros de acción

Apéndice A: Instalación de Visual Studio Express 2012 para Web

Puede instalar Microsoft Visual Studio Express 2012 para Web u otra versión "Express" mediante el Instalador de plataforma web de Microsoft . Las instrucciones siguientes le guían por los pasos necesarios para instalar Visual Studio Express 2012 para Web mediante Instalador de plataforma web de Microsoft.

  1. Ir a https://go.microsoft.com/?linkid=9810169. Como alternativa, si ya ha instalado el Instalador de plataforma web, puede abrirlo y buscar el producto "Visual Studio Express 2012 para Web con el SDK de Windows Azure".

  2. Haga clic en Instalar ahora. Si no tiene Instalador de plataforma web se le redirigirá para descargarlo e instalarlo primero.

  3. Una vez que Instalador de plataforma web está abierto, haga clic en Instalar para iniciar la instalación.

    Install Visual Studio Express

    Instalar Visual Studio Express

  4. Lea todas las licencias y términos de los productos y haga clic en Acepto para continuar.

    Accepting the license terms

    Aceptar los términos de licencia

  5. Espere hasta que finalice el proceso de descarga e instalación.

    Installation progress

    Progreso de la instalación

  6. Cuando finalice la instalación, haga clic en Finalizar.

    Installation completed

    Instalación completada

  7. Haga clic en Salir para cerrar el Instalador de plataforma web.

  8. Para abrir Visual Studio Express para Web, vaya a la pantalla Inicio y escriba "VS Express ", luego haga clic en el icono VS Express para Web.

    VS Express for Web tile

    Icono de VS Express para Web

Apéndice B: Uso de fragmentos de código

Con los fragmentos de código, tendrá todo el código que necesite al alcance de la mano. El documento de laboratorio le indicará exactamente cuándo puede utilizarlos, como se muestra en la siguiente figura.

Using Visual Studio code snippets to insert code into your project

Usar fragmentos de código de Visual Studio para insertar código en el proyecto

Para agregar un fragmento de código mediante el teclado (solo C#)

  1. Coloque el cursor donde desea insertar el código.
  2. Empiece a escribir el nombre del fragmento de código (sin espacios o guiones).
  3. Vea como IntelliSense muestra los nombres de los fragmentos de código coincidentes.
  4. Seleccione el fragmento de código correcto (o siga escribiendo hasta seleccionar todo el nombre del fragmento).
  5. Presione la tecla Tab dos veces para insertar el fragmento de código en la ubicación del cursor.

Start typing the snippet name

Empezar a escribir el nombre del fragmento de código

Press Tab to select the highlighted snippet

Presione la tecla Tab para seleccionar el fragmento de código resaltado

Press Tab again and the snippet will expand

Presione la pestaña de nuevo y el fragmento de código se expandirá

Para agregar un fragmento de código mediante el mouse (C#, Visual Basic y XML) 1. Haga clic con el botón derecho en el lugar donde desea insertar el fragmento de código.

  1. Seleccione Insertar fragmento de código seguido de Mis fragmentos de código.
  2. Seleccione el fragmento de código correspondiente de la lista haciendo clic en él.

Right-click where you want to insert the code snippet and select Insert Snippet

Haga clic con el botón derecho en el lugar donde desea insertar el fragmento de código y seleccione Insertar fragmento de código

Pick the relevant snippet from the list, by clicking on it

Seleccionar el fragmento de código correspondiente de la lista, haciendo clic en él