Search code examples
asp.net-mvc-3asynchronousrecaptchamvcrecaptcha

ASync Recaptcha in MVC3


I've implemented ReCaptcha in MVC3 using ReCaptcha.net NuGet package http://recaptchanet.codeplex.com/wikipage?title=How%20to%20Use%20Recaptcha%20in%20an%20ASP.NET%20MVC%20Web%20Application. All working well, except I'd like to see if I can implement this as Async as it is sometimes quite slow, and we may have some volume on these pages.

The instructions say

RecaptchaVerificationResult recaptchaResult = await recaptchaHelper.VerifyRecaptchaResponse();

if (recaptchaResult != RecaptchaVerificationResult.Success)
{
    ModelState.AddModelError("", "Incorrect captcha answer.");
}

however, this is using the MVC4 await syntax. Is there a way I can use this method within the MVC3 async framework?

I did try a quick hack, converting the controller to AsyncController naming the method with an Async suffix and wrapping the entire action in a Task.Factory.StartNew(() => { ... }); while using the non-async syntax, but RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper(); complains about a lack of HTTPContext.

So, can anyone help me with doing ReCaptcha asynchronously in MVC3


Solution

  • In the end, I've dropped using the NuGet package, and simply process the captcha's using the code below, binding the recaptcha fields in the controller method.

        public bool ProcessCaptcha(string recaptcha_challenge_field, string recaptcha_response_field)
        {
    
            const string verifyUrl = "http://www.google.com/recaptcha/api/verify";
            var res = true;
            var ip = Request.UserHostAddress;
            if (ip == "::1") ip = "127.0.0.1";
            var myParameters = string.Format("privatekey={0}&remoteip={1}&challenge={2}&response={3}", Config.CaptchPriv, ip, recaptcha_challenge_field, recaptcha_response_field);
            using (WebClient wc = new WebClient())
            {
                wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                string HtmlResult = wc.UploadString(verifyUrl, myParameters);
                var split = HtmlResult.Split('\n');
                if (split[0] == "false") res = false;
            }
    
            return res;
        }
    

    With this in place, I split my original controller method into a Async/Completed pair, and wrapped the work it does in Task.Factory.StartNew(() => { ... }), following the pattern outlined here http://www.deanhume.com/Home/BlogPost/mvc-asynchronous-controller---the-basics/67 which seems to work perfectly.