Captcha not rendering in MVC4

Jun 3, 2013 at 2:49 PM
I installed CaptchaMvc.Mvc4 nuget package (v 1.3.0) and added this line to my view
@Html.Captcha(5)
but it does not render an image. This is the html it renders
<img id="CaptchaImage" src="">
I downloaded your example, and the same code works and renders the image.

Am I missing something?
Jun 3, 2013 at 3:13 PM
I figured out that routes are causing this issue. I just saw another post here on this issue.

Has this been resolved?
Coordinator
Jun 3, 2013 at 3:14 PM
Hi there,

This code used to generate an image link:
return urlHelper.Action("Generate", "DefaultCaptcha",
                                    new RouteValueDictionary { { TokenParameterName, captchaPair.Key } });
Make sure that your routes are configured to work with this code.

Regards,
Vyacheslav Volkov
Jun 3, 2013 at 3:17 PM
I only have one route so far and it causes troubles.
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("Home", "", new { controller = "Home", action = "Index" });
}
Can you please tell me how to configure it to work with your code?
Jun 3, 2013 at 3:27 PM
Looks like this solved the problem
routes.MapRoute("Captcha", "DefaultCaptcha/Generate", new { controller = "DefaultCaptcha", action = "Generate" });
Coordinator
Jun 3, 2013 at 3:43 PM
In order to control this, you can override methods to generate url, and use the named routes to avoid problems with the routes:
routes.MapRoute("CaptchaRefresh", "DefaultCaptcha/Refresh", new { controller = "DefaultCaptcha", action = "Refresh" });
routes.MapRoute("CaptchaImage", "DefaultCaptcha/Generate", new { controller = "DefaultCaptcha", action = "Generate" });

protected void Application_Start()
{ ...
  var defaultCaptchaManager = (DefaultCaptchaManager)CaptchaMvc.Infrastructure.CaptchaUtils.CaptchaManager;
  defaultCaptchaManager.ImageUrlFactory = (helper, pair) => ImageUrlFactory(defaultCaptchaManager, helper, pair);
  defaultCaptchaManager.RefreshUrlFactory = RefreshUrlFactory;
}

private static string RefreshUrlFactory(UrlHelper urlHelper, KeyValuePair<string, ICaptchaValue> keyValuePair)
{
    return urlHelper.RouteUrl("CaptchaRefresh");
}

private static string ImageUrlFactory(DefaultCaptchaManager captchaManager, UrlHelper urlHelper,
                                KeyValuePair<string, ICaptchaValue> keyValuePair)
{
    return urlHelper.RouteUrl("CaptchaImage", new RouteValueDictionary { { captchaManager.TokenParameterName, keyValuePair.Key } });
}
Regards,
Vyacheslav Volkov
Oct 21, 2013 at 9:03 AM
For me it is showing captcha image as a blank black image after hosting in a public server. Please share me a solution ASAP
Coordinator
Oct 21, 2013 at 9:27 AM
Hi,
Is it happens only in a public server?
What requests the captcha does, can you attach logs using browser-console or plugins, for example FireBug?
Do you use the custom routes?

Regards,
Vyacheslav Volkov
Oct 21, 2013 at 9:51 AM
it is working fine when published it into localhost. but when calling my local host from remote machine the original captcha image is not coming .

i have added the above route and code for global.asax. still not working
Coordinator
Oct 21, 2013 at 10:05 AM
Try to see requests that captcha makes when page is rendered, without logs it is hard to help you.

Regards,
Vyacheslav Volkov
Oct 21, 2013 at 10:23 AM
Edited Oct 22, 2013 at 1:20 PM
http://myhost/DefaultCaptcha/Generate?t=7890d279083847599d82c31fae2e5bb0
this is the request
Coordinator
Oct 21, 2013 at 11:00 AM
Looks normal.
What html-code the captcha generates?
Do you have a link to a page with captcha?

Regards,
Vyacheslav Volkov
Oct 21, 2013 at 11:06 AM
Edited Oct 21, 2013 at 11:23 AM
                        
<script type="text/javascript">
$(function () {$('#671d9ebf2d3a492188844a6466925867').show();});
function ______132a896b172a4e9ca9e396fb6cbda2bb________() { $('#671d9ebf2d3a492188844a6466925867').hide(); $.post("/DefaultCaptcha/Refresh", { t: $('#CaptchaDeText').val() }, function(){$('#671d9ebf2d3a492188844a6466925867').show();}); return false; }</script> 

<img id="CaptchaImage" src="/DefaultCaptcha/Generate?t=3320efe337a24987b5b767bcd0f60e72"><input id="CaptchaDeText" name="CaptchaDeText" type="hidden" value="3320efe337a24987b5b767bcd0f60e72"> <input autocomplete="off" autocorrect="off" id="CaptchaInputText" name="CaptchaInputText" type="text" value="">
Coordinator
Oct 21, 2013 at 11:30 AM
Edited Oct 21, 2013 at 11:31 AM
Strangely, everything looks normal.
By default the captcha uses the SessionStorageProvider that stores the values in session, maybe you have problems with session.
You can try to use the CookieStorageProvider using this code in global.asax:
protected void Application_Start()
{
     CaptchaUtils.CaptchaManager.StorageProvider = new CookieStorageProvider();
     ...
}
Or you can try to add this code in global.asax to log the errors that you have:
public void Application_Error(object sender, EventArgs e)
{
    Exception lastError = Server.GetLastError();
    //Log here...
}
Regards,
Vyacheslav Volkov
Jun 10, 2014 at 6:07 AM
I had the same problem with the graphic not displaying when hosted on a shared web hosting service. It worked fine on the dev machine of course. Happily, using the CookieStorageProvider suggestion worked immediately. Thanks.

Bob
Aug 14, 2014 at 1:39 PM
Hi Bob,
I have added the cookie storage provider but I have the same problem (on the prod machine)
  protected void Application_Start()
        {
            CaptchaUtils.CaptchaManager.StorageProvider = new CookieStorageProvider();

...
}
Could you tell me what's wrong with my code ?

Thanks,
Pierre
Coordinator
Aug 15, 2014 at 3:13 AM
Edited Aug 15, 2014 at 3:14 AM
Hi Pierre,
Can you provide more information about the problem, or could you please give a demo project to demonstrate this issue?
When did it happened, during debugging or only on production?
Which version of CaptachMvc are you using?
Which version of MVC are you using?
Did you have any exception when the captcha was created?

Regards,
Vyacheslav Volkov
Aug 18, 2014 at 12:20 PM
Hi,
I am using the same code provided by the example.
The Mvc version is 5.
It works really well during debugging. It happened only on production.
I don't have any exception. The hosting provider is OVH.

Thank you very much.
Pierre
Coordinator
Aug 18, 2014 at 1:53 PM
Hi there,
Read this thread, this may be due to the fact that the picture is loaded more than once.
In the next version I will fix this problem. Try this code:
public class StorageProviderWrapper : IStorageProvider
{
    #region Fields

    private const string TokensKey = "~tokens~";
    private readonly IStorageProvider _externalProvider;

    //The maximum number of view for drawing value.
    private readonly int _maxNumberOfView;

    #endregion

    #region Constructors

    public StorageProviderWrapper(IStorageProvider externalProvider, int maxNumberOfView)
    {
        _externalProvider = externalProvider;
        _maxNumberOfView = maxNumberOfView;
    }

    #endregion

    #region Properties

    protected IDictionary<string, int> Tokens
    {
        get
        {
            HttpSessionState httpSessionState = HttpContext.Current.Session;
            var dict = httpSessionState[TokensKey] as IDictionary<string, int>;
            if (dict == null)
                dict = new ConcurrentDictionary<string, int>();
            httpSessionState[TokensKey] = dict;
            return dict;
        }
    }

    #endregion

    #region Implementation of IStorageProvider

    public bool IsContains(string token, TokenType tokenType)
    {
        return _externalProvider.IsContains(token, tokenType);
    }

    public void Add(KeyValuePair<string, ICaptchaValue> captchaPair)
    {
        _externalProvider.Add(captchaPair);
        if (!Tokens.ContainsKey(captchaPair.Key))
            Tokens[captchaPair.Key] = 0;
    }

    public bool Remove(string token)
    {
        return _externalProvider.Remove(token);
    }

    public ICaptchaValue GetValue(string token, TokenType tokenType)
    {
        ICaptchaValue captchaValue = _externalProvider.GetValue(token, tokenType);
        if (tokenType == TokenType.Drawing)
        {
            int value;
            //Getting value of number of view, if it is greater than need, removing it.
            if (!Tokens.TryGetValue(token, out value) || value >= _maxNumberOfView)
                Tokens.Remove(token);
            else
            {
                //clean up validation value.
                _externalProvider.GetValue(token, TokenType.Validation);
                _externalProvider.Add(new KeyValuePair<string, ICaptchaValue>(token, captchaValue));
                value++;
                Tokens[token] = value;
            }
        }
        else
            Tokens.Remove(token);
        return captchaValue;
    }

    #endregion
}


protected void Application_Start()
{
    CaptchaUtils.CaptchaManager.StorageProvider = new StorageProviderWrapper(new CookieStorageProvider(), 3);
    ...
}
I hope this helps.

Regards,
Vyacheslav Volkov