recaptcha-net icon indicating copy to clipboard operation
recaptcha-net copied to clipboard

Multiple reCAPTCHAs on same page only renders the first control

Open SteveElmer opened this issue 8 years ago • 9 comments

Hello. I have used reCAPTCHA for .NET on several of my sites. I am currently working with a legacy site that has two html forms on the same page. While recaptcha for .net is working on other pages, it only renders and works for the first form on the page with two forms. After some googling it looks as if this is something supported by the API. See http://mycodde.blogspot.com/2014/12/multiple-recaptcha-demo-same-page.html. Is this something you could fold into your reCAPTCHA for .NET? Thanks!

SteveElmer avatar Jul 28 '15 14:07 SteveElmer

reCAPTCHA for .NET is not designed to be hosted as multiple instances in a single page. However, its a relevant use case and I will keep it in mind for the next major release (v2.0). I will keep this issue open as a reminder.

tanveery avatar Jul 31 '15 18:07 tanveery

Yeah, after poking around a bit, I gathered it wasn't designed for that. Thank you for considering it for the next version. Any idea when that might be?

SteveElmer avatar Aug 10 '15 15:08 SteveElmer

Has anyone have a solution for this yet? Or does the author know when it would be added to the new version?

smolinacadena avatar Jan 09 '17 22:01 smolinacadena

Use: render=explicit&onload=onloadCallback

ngamai-nvg avatar Jan 10 '17 04:01 ngamai-nvg

this is still not fixed right?

ademgashi avatar May 03 '17 13:05 ademgashi

I have two forms in the same page. Is it possible to have only one captcha working for both forms? I first thought about adding one instance for each form....then I ended up here.

AlissonRS avatar Aug 08 '17 21:08 AlissonRS

So I decided to make a pull request with a simple fix for this. I followed suggestions in this SO question.

AlissonRS avatar Aug 09 '17 12:08 AlissonRS

I see that the last release is 2 years ago ? I need your fix @AlissonRS @tanveery Are you still maintaining this project ? Do you plan to make a new release soon ?

Thanks

Jerome2606 avatar Aug 10 '17 09:08 Jerome2606

@AlissonRS I used your fixes but It was not fit with my needs.

I had to modify the HtmlHelper.

What I need is to have my forms in modal render the captcha. So in one page have multiple forms with for each a working captcha.

I try to modify your fork but I'm not able to do it. So for the ones that wants the same thing than me, use the @AlissonRS fork and change Recaptcha2HtmlHelper.cs to :

 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * =========================================================================================================================== */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace Recaptcha.Web
{
  /// <summary>
  /// Represents the functionality to generate HTML for Recaptcha API v2.0.
  /// </summary>
  public class Recaptcha2HtmlHelper : RecaptchaHtmlHelperBase
  {
    #region Constructors

    /// <summary>
    /// Creates an instance of the <see cref="Recaptcha2HtmlHelper"/> class.
    /// </summary>
    /// <param name="publicKey">Sets the public key to be part of the recaptcha HTML.</param>
    public Recaptcha2HtmlHelper(string publicKey)
        : base(publicKey)
    {
      DataType = null;
      DataSize = null;
    }

    /// <summary>
    /// Creates an instance of the <see cref="Recaptcha2HtmlHelper"/> class.
    /// </summary>
    /// <param name="publicKey">Sets the public key of the recaptcha HTML.</param>
    /// <param name="theme">Sets the theme of the recaptcha HTML.</param>
    /// <param name="language">Sets the language of the recaptcha HTML.</param>
    /// <param name="tabIndex">Sets the tab index of the recaptcha HTML.</param>   
    public Recaptcha2HtmlHelper(string publicKey, RecaptchaTheme theme, string language, int tabIndex)
        : base(publicKey, theme, language, tabIndex)
    {
      DataType = null;
      DataSize = null;
    }

    /// <summary>
    /// Creates an instance of the <see cref="Recaptcha2HtmlHelper"/> class.
    /// </summary>
    /// <param name="publicKey">Sets the public key of the recaptcha HTML.</param>
    /// <param name="theme">Sets the theme of the recaptcha HTML.</param>
    /// <param name="language">Sets the language of the recaptcha HTML.</param>
    /// <param name="tabIndex">Sets the tab index of the recaptcha HTML.</param>    
    /// <param name="useSsl">Determines whether to use SSL in reCAPTCHA API URLs.</param>
    public Recaptcha2HtmlHelper(string publicKey, RecaptchaTheme theme, string language, int tabIndex, SslBehavior useSsl)
        : base(publicKey, theme, language, tabIndex, useSsl)
    {
      DataType = null;
      DataSize = null;
    }

    /// <summary>
    /// Creates an instance of the <see cref="Recaptcha2HtmlHelper"/> class.
    /// </summary>
    /// <param name="publicKey">Sets the public key of the recaptcha HTML.</param>
    /// <param name="theme">Sets the theme of the recaptcha HTML.</param>
    /// <param name="language">Sets the language of the recaptcha HTML.</param>
    /// <param name="tabIndex">Sets the tab index of the recaptcha HTML.</param>    
    /// <param name="dataType">Sets the type of the recaptcha HTML.</param>
    /// <param name="dataSize">Sets the size for the recpatcha HTML.</param>
    /// <param name="useSsl">Determines whether to use SSL in reCAPTCHA API URLs.</param>
    public Recaptcha2HtmlHelper(string publicKey, RecaptchaTheme theme, string language, int tabIndex, RecaptchaDataType? dataType, RecaptchaDataSize? dataSize, SslBehavior useSsl)
        : base(publicKey, theme, language, tabIndex, useSsl)
    {
      DataType = dataType;
      DataSize = dataSize;
    }

    /// <summary>
    /// Creates an instance of the <see cref="Recaptcha2HtmlHelper"/> class.
    /// </summary>
    /// <param name="publicKey">Sets the public key of the recaptcha HTML.</param>
    /// <param name="theme">Sets the theme of the recaptcha HTML.</param>
    /// <param name="language">Sets the language of the recaptcha HTML.</param>
    /// <param name="tabIndex">Sets the tab index of the recaptcha HTML.</param>    
    /// <param name="dataType">Sets the type of the recaptcha HTML.</param>
    /// <param name="dataSize">Sets the size for the recpatcha HTML.</param>
    /// <param name="useSsl">Determines whether to use SSL in reCAPTCHA API URLs.</param>
    /// <param name="dataCallback">Sets the data-callback property of the recaptcha HTML.</param>    
    /// <param name="dataExpiredCallback">Sets the data-expired-callback property of the recaptcha HTML.</param>
    public Recaptcha2HtmlHelper(string publicKey, RecaptchaTheme theme, string language, int tabIndex, RecaptchaDataType? dataType, RecaptchaDataSize? dataSize, SslBehavior useSsl, string dataCallback, string dataExpiredCallback, bool renderApiScriptTag)
       : base(publicKey, theme, language, tabIndex, useSsl, dataCallback, dataExpiredCallback)
    {
      DataType = dataType;
      DataSize = dataSize;
      DataCallback = dataCallback;
      DataExpiredCallback = dataExpiredCallback;
      RenderApiScriptTag = renderApiScriptTag;
    }

    #endregion Constructors

    #region Properties

    /// <summary>
    /// Gets or sets the size of the reCAPTCHA control.
    /// </summary>
    public RecaptchaDataSize? DataSize
    {
      get;
      set;
    }

    /// <summary>
    /// Gets or sets they type of the reCAPTCHA control.
    /// </summary>
    public RecaptchaDataType? DataType
    {
      get;
      set;
    }

    #endregion Properties

    #region Public Methods

    /// <summary>
    /// Gets the recaptcha's HTML that needs to be rendered in an HTML page.
    /// </summary>
    /// <returns>Returns the HTML as an instance of the <see cref="String"/> type.</returns>
    public override string ToString()
    {
      StringBuilder sb = new StringBuilder();

      string lang = "?";

      if (!String.IsNullOrEmpty(Language))
      {
        lang = string.Format("?hl={0}&", Language);
      }

      bool doUseSsl = false;

      if (UseSsl == SslBehavior.DoNotUseSsl)
      {
        doUseSsl = false;
      }
      else if (UseSsl == SslBehavior.AlwaysUseSsl)
      {
        doUseSsl = true;
      }
      else if (UseSsl == SslBehavior.SameAsRequestUrl)
      {
        doUseSsl = HttpContext.Current.Request.IsSecureConnection;
      }

      var protocol = "https://";

      if (!doUseSsl)
      {
        protocol = "http://";
      }

        if (RenderApiScriptTag)
        {
            sb.Append(string.Format("<script src=\"{0}www.google.com/recaptcha/api.js{1}render=explicit&onload=onloadCallback\" async defer></script>", protocol, lang));
            sb.Append(string.Format("<script>var onloadCallback = function() {{ var captchas = document.getElementsByClassName('g-recaptcha'); for (var i = 0; i < captchas.length; i++) {{ grecaptcha.render(captchas[i], {{ 'sitekey' : '{0}'}}); }} }};</script>", PublicKey));
        }

      sb.Append(string.Format("<div class=\"g-recaptcha\" data-sitekey=\"{0}\"", PublicKey));

      if (Theme != RecaptchaTheme.Default)
      {
        var theme = "light";

        if (Theme == RecaptchaTheme.Dark)
        {
          theme = "dark";
        }

        sb.Append(string.Format(" data-theme=\"{0}\"", theme));
      }

      if (TabIndex != 0)
      {
        sb.Append(string.Format(" data-tabindex=\"{0}\"", TabIndex));
      }

      if (!String.IsNullOrEmpty(DataCallback))
      {
        sb.Append(String.Format(" data-callback=\"{0}\"", DataCallback));
      }

      if (!String.IsNullOrEmpty(DataExpiredCallback))
      {
        sb.Append(String.Format(" data-expired-callback=\"{0}\"", DataExpiredCallback));
      }

      if (DataSize != null)
      {
        string dataSize = null;

        switch (DataSize)
        {
          case RecaptchaDataSize.Compact:
            dataSize = "compact";
            break;
          default:
            dataSize = "normal";
            break;
        }

        sb.Append(string.Format(" data-size=\"{0}\"", dataSize));
      }

      if (DataType != null)
      {
        string dataType = null;

        switch (DataType)
        {
          case RecaptchaDataType.Audio:
            dataType = "audio";
            break;
          default:
            dataType = "image";
            break;
        }

        sb.Append(string.Format(" data-type=\"{0}\"", dataType));
      }

      sb.Append("></div>");

      return sb.ToString();
    }

    #endregion Public Methods
  }
}

Jerome2606 avatar Aug 11 '17 14:08 Jerome2606