Inyección de parámetros en acciones ASP.NET MVC (y III)

ASP.NET MVCEn este tercer y último post de la serie (ir al primero o segundo) , vamos a ver una última técnica para realizar inyección de parámetros a acciones ASP.NET MVC que, aunque aporta menos a la hora de comprender las misteriosas interioridades del framework, es ciertamente mucho más cómoda y práctica en caso de que deseemos aplicar esta técnica.

Recapitulando un poco, queremos pasar de un planteamiento en el que el controlador es el que recibe mediante su constructor todas las dependencias que necesitan sus acciones, a otro en el que sean las propias acciones las que reciben los componentes de los que dependen.

Por tanto, pasaríamos de esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class HomeController: Controller
{
    private readonly INotificationServices _notificationServices;
    private readonly IProductServices _productServices;
 
    public HomeController(INotificationServices notificationServices,
                          IProductServices productServices)
    {
        _notificationServices = notificationServices;
        _productServices = productServices;
    }
 
    [HttpPost]
    public ActionResult Contact(ContactViewModel vm)
    {
        if (!ModelState.IsValid) return View();
        _notificationServices.NotifyContact(vm.Name, vm.Email, vm.Text);
        return RedirectToAction("Thankyou");
    }
 
    public ActionResult Products()
    {
        return View(_productServices.GetAll());
    }
 
    [...]
}

A esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class HomeController: Controller
{
    public HomeController()
    {
    }
 
    [HttpPost]
    public ActionResult Contact(ContactViewModel vm,
                                INotificationServices notificationServices)
    {
        if (!ModelState.IsValid) return View();
        notificationServices.NotifyContact(vm.Name, vm.Email, vm.Text);
        return RedirectToAction("Thankyou");
    }
 
    public ActionResult Products(IProductServices productServices)
    {
        return View(productServices.GetAll());
    }
 
    [...]
}

Pero ojo, antes de continuar, un pequeño disclaimer:

Esta técnica no es especialmente recomendable en la mayoría de escenarios, puesto que puede ocultar dependencias y propiciar la aparición de controladores extensos y con demasiadas responsabilidades. Aún así, es un ejercicio interesante para conocer los mecanismos de funcionamiento internos del framework ASP.NET MVC.

En los artículos anteriores hemos visto cómo conseguirlo manualmente usando dos puntos de extensibilidad del framework, el action invoker y el model binder. En esta ocasión vamos a ver cómo Autofac, el popular contenedor de IoC, nos lo da prácticamente solucionado.

Lo primero que tenemos que hacer, como siempre, es instalar la extensión específica para MVC 4 a través de Nuget:

PM> install-Package Autofac.Mvc4
Attempting to resolve dependency 'Autofac (≥ 3.0.0)'.
Installing 'Autofac.Mvc4 3.0.0'.
Successfully installed 'Autofac.Mvc4 3.0.0'

A continuación, creamos una clase en App_Start para configurar los aspectos relativos al contenedor de inversión de control e inyección de dependencias:

public static class IocConfig
{
    public static void Setup()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<ProductServices>()
               .As<IProductServices>().InstancePerHttpRequest();
        builder.RegisterType<NotificationServices>()
               .As<INotificationServices>().InstancePerHttpRequest();

        builder.RegisterType<ExtensibleActionInvoker>()
               .As<IActionInvoker>()
               .WithParameter("injectActionMethodParameters", true);

        builder.RegisterControllers(Assembly.GetExecutingAssembly())
               .InjectActionInvoker();

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
    }
}

En el código anterior encontramos:

  • En primer lugar, el registro de los interfaces IProductServices e INotificationServices, para que puedan ser resueltos correctamente.  
  • A continuación se registra la clase ExtensibleActionInvoker, propia de Autofac, como el action invoker a usar en nuestra aplicación. Se le indica, además, que debe inyectar valores para los parámetros de las acciones, que es justo lo que andábamos buscando.  
  • Por último, se registran los controladores con el nuevo action invoker, y se establece como dependency resolver del sistema el facilitado también por Autofac.

Una vez hecho esto, sólo necesitamos llamar al método Setup() desde el global.asax.cs para que se ejecute al arrancar el sistema, ¡y esto es todo! Con esos simples pasos tendremos funcionando nuestra aplicación ASP.NET MVC con inyección de parámetros automática, utilizando para su resolución el contenedor de IoC Autofac.

El ejemplo desarrollado en este post podéis descargarlo desde Skydrive.

Publicado en http://www.variablenotfound.com/2013/06/inyeccion-de-parametros-en-acciones_18.html

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *