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;
}