I have jsut tested the control, it still not working on multi forms (more than 1 form). For example, if you have a form in content and a form footer, which are both using New reCaptcha controls, none of them can pass validation. Especially, the first form (according to the position in your HTML code) Captcha control will be disappeared after click submit once.
I had fixed the when I worked on my project on Feb in a day. 3 areas need to be updated.
1) Render -> I had to add multiple callback js functions for control itself and also the CaptchaCallback loop callback function.
2) OnInit -> I had to register all callback functions - CaptchaCallback (loop in the function) and individual loop for all control in page. (I would think ReCaptcha control would callback individually. However, I need to register all callback functions in my test - CaptchaCallback (loop all same controls in page in the function) AND CaptchaCallBack_[Control client id] loop to register same controls callback functions. By logic, should be either one would work. However, may be caused by 2 control will have 2 init that override another one register, so I do register all of the callback function to fix the disappearing problem)
3) The first 2 will fix the disappear issue. However, the validation still cannot be passed because the GetCoupledRequestFormValue function cannot return correct value when there are more than 1 form, it will only return the first control value (wherever which come first). Since it is HTML input value, with the same field name in 2 control, it will become "value1,value2". if you are submitting form 2, you need to update this part to provide the correct value pass to API for validation.
HERE are the code I updated.
/// <summary>
/// Control init event
/// </summary>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.Validators.Add(this);
IsMultipleInstance = false;
ScriptManager.RegisterStartupScript(this, typeof(Page), UniqueID, "if (typeof(CaptchaCallback) === 'function') { CaptchaCallback(); }", true);
foreach (var validator in Page.Validators)
{
if (validator is NewRecaptchaControl)
{
ScriptManager.RegisterStartupScript(this, typeof(Page), "CallBack_" + ((NewRecaptchaControl)validator).ClientID, "if (typeof(CaptchaCallback_" + ((NewRecaptchaControl)validator).ClientID + ") === 'function') { CaptchaCallback_" + ((NewRecaptchaControl)validator).ClientID + "(); }", true);
}
}
}
/// <summary>
/// Control render event.
/// </summary>
/// <param name="writer">HtmlTextWriter parameter</param>
protected override void Render(HtmlTextWriter writer)
{
// Render the div tag for nesting the reCaptcha
writer.WriteBeginTag("div");
if (!string.IsNullOrEmpty(Theme))
{
writer.WriteAttribute("data-theme", Theme);
}
if (!string.IsNullOrEmpty(DataType))
{
writer.WriteAttribute("data-type", DataType);
}
writer.Write("></div>");
if (!IsMultipleInstance)
{
IsMultipleInstance = true;
// Render the reCaptcha scripts
string sUrl = RECAPTCHA_API_URL.Replace("onload=CaptchaCallback&", "onload=CaptchaCallback_" + this.ClientID + "&");
writer.Write("<script src=\"{0}\" async defer></script>", RECAPTCHA_API_URL);
writer.Write("<script>");
writer.Write("var CaptchaCallback_" + this.ClientID + " = function(){");
writer.Write("if (document.getElementById('" + this.ClientID + "') != null && (typeof grecaptcha!== 'undefined')) { grecaptcha.render(document.getElementById('" + this.ClientID + "'), {'sitekey' : '" + SiteKey + "'}); }");
writer.Write("};");
writer.Write("var CaptchaCallback = function(){");
foreach (var validator in Page.Validators)
{
if (validator is NewRecaptchaControl)
{
writer.Write("if (document.getElementById('" + ((NewRecaptchaControl)validator).ClientID + "') != null && (typeof grecaptcha!== 'undefined')) { grecaptcha.render(document.getElementById('" + ((NewRecaptchaControl)validator).ClientID + "'), {'sitekey' : '" + SiteKey + "'}); }");
}
}
writer.Write("};");
writer.Write("</script>");
}
base.Render(writer);
}
/// <summary>
/// Get form field value
/// </summary>
/// <param name="formField">Field name to get its value from</param>
private string GetCoupledRequestFormValue(string formField)
{
// Get form value
var fieldValue = Context.Request.Form[formField];
if (!string.IsNullOrEmpty(fieldValue))
{
var fieldValuesArray = fieldValue.Split(new[] { ',' });
int iCount = -1;
foreach (var validator in Page.Validators)
{
if (validator is NewRecaptchaControl)
{
iCount += 1;
if (this.ClientID == ((NewRecaptchaControl)validator).ClientID)
{
break;
}
}
}
if (fieldValuesArray.Length > 0)
{
fieldValue = fieldValuesArray[iCount];
}
else
{
fieldValue = string.Empty;
}
}
return fieldValue;
}
Hope this can help everyone who need to put this control into more than one form in the same page. Thank you :)