tags:

views:

120

answers:

2

I'm part of the way through implementing a native CAPTCHA (i.e. not reCaptcha) solution in my app. I've built it along the lines of Sanderson's book, Pro ASP.NET MVC Framework. It's built into a HtmlHelper class so I can call it in my view like

<%= Html.Captcha("nameOfGeneratedCaptchaIdField")%>

However, to use this I'll need a way to allow for it's re-generation. i.e. If you can't read this, click [here].

This [here] I want to be a controller action that generates the captcha image and spits back the html. (I'll use this in an Ajax.ActionLink link.)

But I'm having trouble figuring out how to do this in my controller. How do I get a handle on the HtmlHelper that's required by a HtmlHelper

public ActionResult RegenerateCaptcha(string name)
{
    var myHtmlHelper = ???;
    var newCaptcha = Captcha.Helpers.CaptchaHelper.Captcha(myHtmlHelper, name);


    if (Request.IsAjaxRequest())
    {
        return Content(newCaptcha.ToString());
    }
    else
    {
        return Content(newCaptcha.ToString());
    }
}

My Captcha Helper is coded as:

// this is invoked in a view by <%= Html.Captcha("myCaptcha") %>
public static string Captcha(this HtmlHelper html, string name)
{
    // Pick a GUID to represent this challenge
    string challengeGuid = Guid.NewGuid().ToString();
    // Generate and store a random solution text
    var session = html.ViewContext.HttpContext.Session;
    session[SessionKeyPrefix + challengeGuid] = MakeRandomSolution();

    // Render an <IMG> tag for the distorted text,
    var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
    string url = urlHelper.Action("Render", "CaptchaImage", new{challengeGuid});
    // fill it with a newly rendered image url, 
    // plus a hidden field to contain the challenge GUID
    return string.Format(ImgFormat, name, challengeGuid, url);
}

I guess I can just copy that out of the Helper and paste it into my controller action, but that seems a bit ghetto...

Thanks.

+2  A: 

You don't have to create html helpers in your controller. You should create partial view returning captcha and return PartialViewResult:

public PartialViewResult Captcha()
{
    return PartialView("Captcha");
}
LukLed
I agree. This is always something that is best left to a PartialView and not something you'd render in a controller method. Separate out presentation and leave it to a View.
Nissan Fan
Awesome. Works like a charm! Thanks!
Scott
A: 

@LukLed is right. PartialView is more suitable for this, also you may want to look at this.