This page looks best with JavaScript enabled

Recaptcha, ASP.NET MVC, SimpleModal y un poco de Ajax…

 ·  ☕ 4 min  ·  ✍️ eiximenis

Nota: Este post ha sido importado de mi blog de geeks.ms. Es posible que algo no se vea del todo "correctamente". En cualquier caso puedes acceder a la versión original aquí

Hola família!

En los dos últimos posts (http://geeks.ms/blogs/etomas/archive/2009/04/14/mostrar-un-formulario-modal-con-asp-net-mvc-y-ajax.aspx y http://geeks.ms/blogs/etomas/archive/2009/04/15/mostrar-un-formulario-modal-con-asp-net-mvc-y-ajax-ii.aspx) comenté como he usado SimpleModal, junto con ASP.NET MVC para mostrar un formulario modal y comunicarlo via AJAX con nuestro controlador.

En mi caso, este formulario era el formulario de registro… y para evitar los spammers (tal y como diría cierto ministro, yo no digo que haya que prohibir el spam, pero yo lo prohibiría :p) decidí usar un captcha.

Paso 1: El captcha

Nevagando por esas webs de dios, llegué a Recaptcha un sitio donde ofrecen de forma totalmente gratuita un servicio de captchas bastante interesante… Empecé a ver como integrar Recaptcha en ASP.NET MVC… la API no es muy complicada y hay gente que ha hecho utilidades para casi todos lenguajes de servidor (como se puede ver en la página de recursos de Recaptcha). Aunque no aparece en esta página de recursos, googleando un poco más vi que Andrew Wilinksi ya había hecho una API para recaptcha usando ASP.NET MVC Beta 1: RecaptchaMvc. En su blog anuncia que es para la Beta 1 de ASP.NET MVC, así que me descargue el código fuente desde http://recaptchamvc.codeplex.com/SourceControl/ListDownloadableCommits.aspx (el changeset 27773) y lo compilé contra la versión final de ASP.NET MVC.

El resultado es que NO compila, debido al uso de la interfaz IValueProvider y la clase DefaultValueProvider, que existían en la Beta y que fueron eliminadas. La solución es bastante simple, en el fichero controllerextensions.cs, cambiar las referencias a IValueProvider por IDictionary<string, ValueProviderResult>. Al final del post adjunto el fichero modificado para que compile contra la versión final. Este es el único fichero que debe ser modificado.

RecaptchaMvc incorpora métodos de extensión para HtmlHelper, de forma que poner un Captcha es tan sencillo como:

<%= Html.Recaptcha(this.Model) %>

Entiendendo que estamos en una vista tipada cuyo tipo de modelo es IRecaptchaModelState, una interfaz proporcionada por RecaptchaMvc, que también proporciona la clase RecaptchaModelState que implementa la interfaz. Dicha clase espera nuestra clave pública de Recaptcha.

Paso 2: El formulario modal…

Y este post se habría terminado ya, si en mi caso yo no estuviese mostrando el captcha en un formulario modal via SimpleModa. A ver, a grandes rasgos el problema es que la llamada a Html.Recaptcha, genera un tag <script>. Si mostramos un formulario usando Ajax, lo que hacermos básicamente es rellenar un <div> via javascript con cierto contenido html. En este caso, los tags <script> son ignorados, por lo que el captcha no se ve…

La solución? Una vez esté cargado el formulario modal, llamar via Ajax a recaptcha y mostrar entonces el captcha. Por suerte esto es posible porque la gente de recaptcha ofrecen una API Ajax, porque si no… buf! En la página de la API cliente de recaptcha se describe como funciona la API de recaptcha si queremos usar Ajax. Hay también un ejemplo y la verdad es que es bastante sencillo… De hecho son dos pasos muy sencillos:

  1. Incluir el fichero de script recaptcha_ajax.js
  2. Llamar a la función Recaptcha.Create. Esta función espera la clave pública, el ID del objeto DOM a rellenar con el captcha y un objeto con varias propiedades adicionales para personalizar el captcha.

Por lo tanto, lo que he hecho ha sido:

En la vista principal (la que muestra el popup cuando se pulsa un enlace), que en mi caso se llama Home/Index.aspx, he añadido el tag <script>:

<script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js"></script>

Y luego he definido una función showRecaptcha, que llama Recaptcha.Create:

<script type="text/javascript">
    function showRecaptcha() {
Recaptcha.create("clave_publica_de_recaptcha",
"div_recaptcha", {
theme: "red",
tabindex: 0 }); } </script>

Finalmente, llamo a esta función en cuanto se ha mostrado el formulario modal. Para ello uso el callback onOpen de SimpleModal. Si mirais mi post anterior, vereis que ya usaba este callback para añadir un manejador de eventos javascript para ir comprobando (via AJAX) si el login del usuario estaba libre o no, sin necesidad de hacer submit de todo el popup. En mi caso tenía una función popup_open, y ha sido en ella que he añadido el código para mostrar el captcha:

function popup_open(dialog) {
    dialog.overlay.fadeIn('slow', function() {
        dialog.container.fadeIn('slow', function() {
            dialog.data.fadeIn('slow', function() {
                showRecaptcha();
// resto de código... }); }); }); }

Paso 3: Comprobar el captcha

Esto, usando RecaptchaMvc es muy fácil. En mi caso, cuando el usuario pulsa el botón “Enviar” de mi popup, se hace un POST a una URL gestionada por la acción Signup del controlador Account, cuyo código es:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Signup(FormCollection values)
{
    string privateKey = this.GetRecaptchaPrivateKey();
    var response = this.TryValidateRecaptcha
        (privateKey, values.ToValueProvider());
    if (response.IsValid) {
        // Recaptcha ha sido Ok
    }
    else {
        // Recapcha ha ido mal
    }
}

Muy simple: Obtenemos la clave privada de Recaptcha (el método GetRecaptchaPrivateKey) es un método extensor mío, que obtiene la clave privada que guardo en el web.config. Luego simplemente llamamos a TryValidateRecaptcha (método extensor que incorpora RecapthcaMvc) y con esto ya sabemos si el captcha es correcto o no!

Y aquí teneis una captura de pantalla con todo funcionando:

image

(Sí, sí… el estilo es muy… ASP.NET MVC :p :p :p)

Saludos!

Enlace del fichero controllerextensions.cs de RecaptchaMvc preparado para ASP.NET MVC versión final.

Si quieres, puedes invitarme a un café xD

eiximenis
ESCRITO POR
eiximenis
Compulsive Developer