views:

480

answers:

2

Ok...

I've downloaded and implemented this Recaptcha implementation for MVC which uses the ModelState to confirm the validity of the captcha control.

It works brilliantly... except when I start to use it in an AJAX Form.

In a nutshell, when a div is re-rendered with AJAX, the ReCaptcha that it should contain does not appear, even though the relevant <scripts> are in the source after the partial render.

Code Below.

 using (Ajax.BeginForm("CreateComment", "Blog", 
        new AjaxOptions() { HttpMethod = "POST", 
         UpdateTargetId = "CommentAdd", OnComplete="ReloadRecaptcha", 
         OnSuccess = "ShowComment", OnFailure = "ShowComment", 
         OnBegin = "HideComment" }))
{%>
    <fieldset class="comment">
        <legend>Add New Comment</legend>
        <%= Html.ValidationSummary()%>
        <table class="postdetails">
            <tbody>
                <tr>
                    <td rowspan="3" id="blahCaptcha">
                        <%= Html.CreateRecaptcha("recaptcha", "blackglass") %>
                    </td>
                    .... Remainder of Form Omitted for Brevity

I've confirmed the Form is perfectly functional when the Recaptcha Control is not present and the Javascript calls in the AjaxOptions are all working fine.

The problem is that if the ModelState is Invalid as a result of the Recaptcha or some other validation, then the ActionResult returns the View to reshow the form.

    [RecaptchaFilter(IgnoreOnMobile = true)]
    [HttpPost]
    public ActionResult CreateComment(Comment c)
    {
        if (ModelState.IsValid)
        {
            try
            {
                //Code to insert Comment To DB
                return Content("Thank You");
            }
            catch
            {
                ModelState.AddRuleViolations(c.GetRuleViolations());
            }
        }
        else
        {
            ModelState.AddRuleViolations(c.GetRuleViolations());
        }
        return View("CreateComment", c);
   }

When it's InValid and the form posts back, for some reason the ReCaptcha Control does not re-render. I've checked the source and the <script> & <noscript> blocks are present in the HTML so the HTML Helper function below is obviously working

<%= Html.CreateRecaptcha("recaptcha", "blackglass") %>

I assume this has something to do with scripts injected into the DOM by AJAX are not re-executed.

As you can see from the HTML snippet above, I've tried to add an OnComplete= javascript function to re-create the Captcha on the client side, but although the script executes with no errors, it doesn't work. OnComplete Function is.

    function ReloadRecaptcha() {
        Recaptcha.create("my-pub-key", 'blahCaptcha', { 
            //blahCaptcha is the ID of the <td> where the ReCaptcha should go.
            theme: 'blackglass'
            });
    }

Can anyone shed any light on this ?

Thanks, Eoin C

A: 

I assume The Html.CreateRecaptcha() extension creates a <div> or something that the scripts update with the captcha image. Shouldn't the Recaptcha.create() function pass 'recaptcha' (the id of the element) instead of 'blahCaptcha' (the name of the td)?

Take a look at the HTML produced by Html.CreateRecaptcha and try referring to the id of the element created by that extension instead of the id of the containing td.

Dave Swersky
Have tried that too... there is a div there ID=recaptcha_widget_divSo on the initial load the Html.CreateCaptcha generates just the <scripts> and the execution of the scripts generates the output html for the recaptcha form.On the AJAX rerun, the HTML.CreateCaptcha generates the <script>, AJAX re-injects them into my <TD> but the scripts aren't executed so the <div> you mention never even exists after the partial render.
Eoin Campbell
+1  A: 

Figured out a solution to this.

I completely removed the client side rendering of the Captcha with the HTML Helper.

Instead, the Filter stays in place on the server side for doing the ModelState validation etc...

And the client side rendering is all done using the ReCaptcha AJAX Api's from http://recaptcha.net/fastcgi/demo/ajax and http://api.recaptcha.net/js/recaptcha_ajax.js

Everytime the partial post occurs, the captcha disappears, everytime it completes, the OnComplete script recreates it.

Eoin Campbell