jueves, 6 de noviembre de 2014

WP - Atributo de MVC para filtrar acciones para solicitudes AJAX

Esta entrada ha sido reposteada por error, pero utilizando Gists para mejor legibilidad del código, acá: http://itsouvenirs.blogspot.com/2018/01/wp-atributo-de-mvc-2-para-filtrar.html

Ya llevo un par de meses trabajando con ASP.NET MVC Framework 2, y debo decir que me ha encantado. Y sé que van por la versión 4, pero en el trabajo contamoscon Visual Studio 2008, así que hay que aprovechar lo que se tiene, y debo decir que en realidad no es poco.

En esta ocasión quiero mostrar una forma de crear un atributo de filtrado para acciones que deben ser ejecutadas solamente mediante solicitudes Ajax. Esto es útil para acciones que deseamos utilizar exclusivamente para estas solicitudes, y que queremos que el usuario común tenga acceso a ellas solamente a través de esta forma, mediante alguna interacción con la interfaz de usuario (UI), por ejemplo.

Primero, es necesario encontrar una forma de identificar que el tipo de solicitud es XML HTTP request, que es la clase de solicitudes que se hacen mediante AJAX. El objeto HttpRequest del que disponemos en una aplicación ASP.NET no cuenta con un método propio para identificar este tipo de solicitud, por lo que es necesario trabajar un poco en esta parte. Para ello, crearemos un método de extensión que se encargue de verificar esto. El método que presento a continuación es prácticamente una copia de la respuesta de Charlino a la pregunta de StackOverflow titulada How to check if request is ajax or not in codebehind – ASP.NET Webforms, que a su vez se basa en el código fuente del MVC Framework (que es open source, o código libre, por cierto).

using System;
using System.Web;
 
namespace MiProyectoMVC.Extensiones
{
    public static class HttpRequestExtensions
    {
        public static bool IsAjaxRequest(this HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("Request es nulo");
            }
 
            return (request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest"));
        }
    }
}
Como puede observarse, el método revisa directamente el encabezado del request, para verificar el tipo de solicitud. Si el tipo de solicitud es XMLHttpRequest, devuelve verdadero, y falso en caso contrario.

Actualización: Existe un método de extensión para la clase HttpRequestBase en el espacio de nombres System.Web.Mvc, con el mismo nombre y funcionalidad que el del método propuesto (IsAjaxRequest). Podría usarse este en vez de crear una nueva extensión, solamente incluyendo el espacio de nombres System.Web.Mvc.

Teniendo este método disponible, podemos proceder a crear el atributo de filtro. Este es un atributo de filtro convencional, por lo que será descendiente o derivado de la clase ActionFilterAttribute. Como se observa a continuación, el atributo es bastante simple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MiProyectoMVC.Extensiones;
 
namespace MiProyectoMVC.Controllers.Atributos
{
    public class XmlHttpRequestAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!filterContext.HttpContext.Request.IsAjaxRequest())
            {
                //Si no es solicitud Ajax, mostramos a una página de error completa
                filterContext.Result = new ViewResult() { ViewName = "Error" };
            }
            base.OnActionExecuting(filterContext);
        }
    }
}
Como puede observarse, todo el proceso de verificación se realiza sobrecargando el método OnActionExecuting, que se ejecuta justo antes de proceder a ejecutar la acción. Acá hacemos uso del método de extensión para verificar si la solicitud (request) es de tipo Ajax, y si no lo es, devolvemos como resultado una vista completa, que bien puede ser una página de error personalizada. Cabe mencionar que digo vista completa porque el resultado a generar es un ViewResult. Dado que sabemos que no es una solicitud Ajax, lo común no sería devolver una vista parcial, sino una página completa (.aspx). También, en vez de devolver de una sola vez la página de error, podríamos redireccionar hacia otra acción que consideremos conveniente, a través de un RedirectResult.

Finalmente, decoramos la acción que deseamos filtrar con el atributo que hemos creado, de la siguiente manera:

//...
 
namespace MiProyectoMVC.Controllers
{
    public class EjemploController : Controller
    {
        // ...
 
        [XmlHttpRequest]
        public ActionResult IndexPartial()
        {
            //...
            return PartialView("IndexPartial");
        }
 
        //...
    }
}
Acá les dejo un enlace que encontré por allí, que tiene varios ejemplos de atributos de filtro de acciones bastante interesantes, que puede que les sean de utilidad: Creating Custom Action Filters in ASP.NET MVC


NOTA: Aunque este atributo fue elaborado y probado en MVC Framework 2, de igual forma es aplicable para las versiones 3, 4 y 5 (posiblemente) del framework.


Cualquier comentario será bien recibido, y como dicen por allí, Happy coding!

Related Articles

0 comentarios:

Publicar un comentario

Con la tecnología de Blogger.