jQuery and Handler i.e. Legacy Code
Working on a legacy code component so the current codebase is using HttpHandlers (yes this is and old pre .NET 2.0 application) and the task is to expand this functionality to allow for a Google reCAPTCHA v3 automated valid user detection.
Client side code
Load the appropriate client side script from Google
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=ClientSide_reCAPTCHAv3Token"></script>
Now when the page has loaded run the client side validation to the server HttpHandler code path with the client identifying token.
<script type="text/javascript">
$(document).ready(function () {
grecaptcha.ready(function() {
grecaptcha.execute('<Google Client reCAPTCA v3 Token>', { action: 'TAG_ACTION' }).then(function (token) {
console.log(token);
console.log(JSON.stringify({ clientToken: token }));
jQuery.ajax({
type: "POST",
url: "<the_old_handler_path.ashx>",
data: JSON.stringify({ clientToken: token }),
contentType: "application/json",
success: function (response) {
console.log(response);
if (!response.success) {
window.location.href = "/";
}
}
});
});
});
});
</script>
Handler Code
Important note to read the application/json from the submitted jQuery POST
Que ¡Important!
var postedData = new StreamReader(context.Request.InputStream).ReadToEnd();
public void ProcessRequest(HttpContext context)
{
var responseText = JsonConvert.SerializeObject(new
{
success = false
});
var postedData = new StreamReader(context.Request.InputStream).ReadToEnd();
if (!string.IsNullOrEmpty(postedData))
{
var parsedData = JsonConvert.DeserializeObject<RecaptchaToken>(postedData);
var secret = ConfigurationManager.AppSettings["reCAPTCHA"];
var verification = AsyncHelper.RunSync(async () => await ValidateCaptcha(parsedData.ClientToken, secret));
responseText = JsonConvert.SerializeObject(new
{
success = verification.Success,
errors = verification.ErrorCodes
});
}
context.Response.ContentType = JsonMimeType;
context.Response.Write(responseText);
}
Also of note to call the async method synchronously this static helper class of AsyncHelper is used
internal static class AsyncHelper
{
private static readonly TaskFactory MyTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return AsyncHelper.MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}