[ASP.NET MVC] Creando una factoria de controladores personalizada

Posted on Actualizado enn


Hola a todos, como ya sabemos, un controlador en ASP.NET MVC no es más que una clase, la cual hereda de la clase Controller, sin embargo dicha clase no tiene un constructor definido, o bueno no al menos uno que podamos ver, dicho esto cuando una clase no tiene un constructor definido (o varios) por defecto si se tiene un constructor para esa clase que no recibe parámetros, ahora bien, en MVC tenemos algo que se conoce como factoría de controladores, cuya principal función es inicializar los controladores usando ese constructor vacío que todos tienen…y de que va todo esto? simple, que pasa cuando tenemos un controlador pero este requiere un constructor personalizado? Por ejemplo, si tenemos el siguiente controlador con un constructor personalizado:

public class HomeController : Controller
{
	private string username = string.Empty;
	public HomeController(string username)
	{
		this.username = username;
	}
}

Ahora si intentamos ejecutar, vamos a obtener el siguiente error:

controllererror

El error anterior se da porque el controlador no tiene un constructor sin parámetros por lo tanto no es posible inicializarlo. Pero y el constructor vacío que tienen todas las clases? Bueno, pues resulta que eso solo aplica cuando no se ha definido ningún constructor en la clase, y como nuestro controlador le definimos uno el otro ahora si desaparece.

Debido al problema anterior, necesitamos definir una nueva forma de inicializar el controlador HomeController y pasarle el parámetro que requiere, y para ello podemos crear una factoría personalizada, básicamente debemos crear una nueva clase que implemente la interfaz IControllerFactory, y en la función CreateController definimos como inicializar el controlador anterior.

Por organización vamos a crear una nueva carpeta llamada Factory, y allí dentro una nueva clase con el nombre CustomControllerFactory que implementa IControllerFactory:

public class CustomControllerFactory : IControllerFactory
{
	public IController CreateController(RequestContext requestContext, string controllerName)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}

	public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}

	public void ReleaseController(IController controller)
	{
		// TODO: Implement this method
		throw new NotImplementedException();
	}
}

Ya con la clase creada, vamos a iniciar a definir lógica para cada método, iniciemos con ReleaseController, cuya función es liberar recursos:

public void ReleaseController(IController controller)
{
	var disposable = controller as IDisposable;
	if (disposable != null)
		disposable.Dispose();
}

Luego vamos con GetControllerSessionBehavior, por el momento vamos a dejar el comportamiento por defecto:

public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
	return SessionStateBehavior.Default;
}

Y finalmente CreateController, donde vamos a especificar la nueva forma de instanciar el controlador que hemos modificado anteriormente:

public IController CreateController(RequestContext requestContext, string controllerName)
{
	if (controllerName.ToLower() == "home")
	{
		var controller = new HomeController("julitogtu");
		return controller;
	}

	var defaultFactory = new DefaultControllerFactory();
	return defaultFactory.CreateController(requestContext, controllerName);
}

Lo que hace el código anterior es validar si el controlador que se esta requiriendo en Home, en caso afirmativo lo instanciamos usando el constructor que hemos creado, en caso que no sea el controlador Home, entonces dejamos que la factoría por defecto haga su trabajo. Ahora el código completo de nuestra factoría:

public class CustomControllerFactory : IControllerFactory
{
	public IController CreateController(RequestContext requestContext, string controllerName)
	{
		if (controllerName.ToLower() == "home")
		{
			var controller = new HomeController("julitogtu");
			return controller;
		}

		var defaultFactory = new DefaultControllerFactory();
		return defaultFactory.CreateController(requestContext, controllerName);
	}

	public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
	{
		return SessionStateBehavior.Default;
	}

	public void ReleaseController(IController controller)
	{
		var disposable = controller as IDisposable;
		if (disposable != null)
			disposable.Dispose();
	}
}

Finalmente, para que la factoría funcione, la llamamos en el evento Application_Start de el Global.asax:

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

Espero el ejemplo les sea interesante, saludos!

6 comentarios sobre “[ASP.NET MVC] Creando una factoria de controladores personalizada

    Gustavo Alzate Sandoval (ElTavo) escribió:
    01/07/2014 en 09:07

    Hola Julio, muy interesante, le veo mucha utilidad para inyección de dependencias, muchas gracias!

    Julio Avellaneda respondido:
    01/07/2014 en 09:10

    Gracias Gustavo, exactamente, allí podemos utilizar algún IcC container, ese será el siguiente🙂

    Christian Sanabria escribió:
    01/08/2014 en 18:52

    Soy realmente novato en MVC, tengo muchos años trabajando con Webforms y no le encuentro uso a esto… hasta donde sé de MVC. Me podrían dar algún ejemplo de su uso por favor. Por cierto si me responden esta semana estaré sin acceso al correo…

      Julio Avellaneda respondido:
      01/08/2014 en 18:57

      Hola Christian, un ejemplo sencillo puede ser si tu controlador requiere usar x clase, como por ejemplo un repositorio, en ese puedes implementar un Ioc container para inyectar la dependencia y tener tu código menos acoplado, saludos.

    […] a todos, en el anterior post (míralo acá) vimos como podemos crear una factoría de controladores personalizada para poder instanciar […]

    […] probamos la aplicación vamos a obtener un error, y por el momento les dejo dos posibles soluciones Creando una factoría de controladores personalizada e Inyectando dependencias con Microsoft […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s