OpenCAPTCHA.org

The following is a sample Challenge service, which collects a Challenge/Answer object from a Challenge-Answer provider service, retains the answer, and exposes the Challenge object to a client or web site, while providing a ValidateAnswer action. This sample uses C# 3.0 and ASP.NET MVC. The URL for this sample when implemented is: http://[hostname]/Challenge, and the output is:

callback_function({
    challenge: "Enter this word: orange",
    format: "text",
    token: "84699989-8FF7-4ee7-9A02-6DDC3A9DDEF4"
})

public class ChallengeController : Controller
{
    // "sibling" controller; normally this would be hosted by someone else on a URL far, far away
    private string CHALLENGEANSWER_PROVIDER_URL
        = new Uri(new Uri( System.Web.HttpContext.Current.Request.Url.Scheme
                  + "://"
                  + System.Web.HttpContext.Current.Request.Headers["Host"]
                  + System.Web.HttpContext.Current.Request.Url.PathAndQuery),
                  "ChallengeAnswer").ToString();

    //
    // GET: /Challenge/

    public ActionResult Index()
    {
        var wc = new WebClient();
        var challengeAnswerJson = wc.DownloadString(CHALLENGEANSWER_PROVIDER_URL);
        var jss = new JavaScriptSerializer();
        var challengeAnswer = jss.Deserialize<ChallengeAnswer>(challengeAnswerJson);
        var ret = new Challenge
                      {
                          challenge = challengeAnswer.challenge,
                          format = challengeAnswer.format, 
                          token = Guid.NewGuid().ToString()
                      };
        System.Web.HttpContext.Current.Application["token:" + ret.token]
            = challengeAnswer;
        var type = "jsonp";
        if (Request["type"] != null) type = Request["type"];
        switch (type.ToLower())
        {
            case "jsonp":
                return Jsonp(ret);
            case "json":
                return Json(ret);
            case "xml":
                return Xml(ret);
        }
        return View();
    }

    //
    // GET: /Challenge/ValidateAnswer

    public ActionResult ValidateAnswer()
    {
        ChallengeAnswer challengeAnswer;
        ChallengeAnswerValidationResult ret;
        try
        {
            challengeAnswer =
                (ChallengeAnswer) System.Web.HttpContext.Current
                                      .Application["token:" + Request["token"]];
            System.Web.HttpContext.Current.Application.Remove("token:" + Request["token"]);
            bool match = false;
            foreach (var answer in challengeAnswer.answer)
            {
                if ((challengeAnswer.caseSensitive && answer == Request["answer"]) ||
                    (!challengeAnswer.caseSensitive && answer.ToLower() == Request["answer"].ToLower()))
                {
                    match = true;
                    break;
                }
            }
            ret = new ChallengeAnswerValidationResult
                          {
                              pass = match
                          };
        } catch (Exception e)
        {
            ret = new ChallengeAnswerValidationResult
                      {
                          error = e.Message
                      };
        }
        var type = "json";
        switch (type)
        {
            case "json":
                return Json(ret);
            case "jsonp":
                return Jsonp(ret);
            case "xml":
                return Xml(ret);
        }
        return View();
    }

    public JavaScriptResult Jsonp(object val)
    {
        var ret = new JavaScriptResult();
        var jsds = new System.Web.Script.Serialization.JavaScriptSerializer();
        var jsval = jsds.Serialize(val);
        ret.Script = Request["callback"] + "(" + jsval + ")";
        return ret;
    }

    public XmlResult Xml(object val)
    {
        var xr = new XmlResult();
        if (val is string) xr.Xml = (string)val;
        else
        {
            var xs = new System.Xml.Serialization.XmlSerializer(val.GetType());
            var ms = new System.IO.MemoryStream();
            xs.Serialize(ms, val);
            ms.Seek(0, System.IO.SeekOrigin.Begin);
            var sr = new System.IO.StreamReader(ms);
            xr.Xml = sr.ReadToEnd();
        }
        return xr;
    }

    public class XmlResult : ActionResult
    {
        public string Xml { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.ContentType = "text/xml";
            context.HttpContext.Response.Write(Xml);
        }
    }

}

[Serializable]
[XmlType("challengeAnswer")]
public class ChallengeAnswer
{
    public string format;
    public string challenge;
    public string[] answer;
    public bool caseSensitive;
}

[Serializable]
[XmlType("challenge")]
public class Challenge
{
    public string challenge;
    public string format;
    public string token;
}
[Serializable]
[XmlType("validateResult")]
public class ChallengeAnswerValidationResult
{
    public bool? pass;
    public string error;
}

ScrewTurn Wiki version 2.0.37. Some of the icons created by FamFamFam.