0

Our goal is to get Google Recaptcha V3 working on a single form on an MVC3 .NET4.5 project. However, I'm struggling to make this work due to the async request to Google for the Recaptcha score.

FE is set up. I set the new token to a hidden field and send the token to the controller. Then, I run this async task and make the validation request to Google. The response comes back with the success message and the score.

I thought I finally had it working using Task.Factory.StartNew(), but it results in System.Threading.Tasks.Task`1[System.Web.Mvc.ActionResult] showing up on the returned view.

Note: It is not an option to upgrade legacy ASP.NET MVC3 project to MVC4.

The hidden field in the view: `

// Other code

@Html.HiddenFor(model => model.Token, new { id="SubscriptionFormModelToken"})

// Other code
`

The token gets set to the hidden field in the JS: ` var your_site_key = '@System.Configuration.ConfigurationManager.AppSettings["ReCaptchaV3PublicKey"]'; console.log('your_site_key', your_site_key);

    $(function () {
        grecaptcha.ready(function () {

        grecaptcha.execute('@System.Configuration.ConfigurationManager.AppSettings["ReCaptchaV3PublicKey"]', { action: 'submit' }).then(function (token) {
            // Set token to hidden field for BE validation
            console.log('newest token:', token);

            var subscriptionFormModelElement = document.getElementById("SubscriptionFormModelToken");
            subscriptionFormModelElement.value = token;
            console.log('subscriptionFormModelElement:', subscriptionFormModelElement);


        });
    });
    })
 </script>

`

Pass the token in and run the task: ` [HttpPost] public async Task SubmitSubscriptionForm(SubscriptionFormModel model, FormCollection collection) {

        //Fetch Google Recaptcha result
        var captchaObject = Task.Factory.StartNew(() => GoogleCaptchaService.VerifyToken(model.Token));

        var captchaResult = captchaObject.Result.Result;

        if (!captchaResult)
        {
            model.RecaptchaResponseIsGood = false;
            return PartialView("Subscription/_SubscriptionForm", model);
        }
        
        // A lot of other code runs to save the Form Results to the db if captchaResult is successful. 
    }

`

Task runs through. Response comes back with success/fail and the score: `public class GoogleCaptchaService {

    //Google Recaptcha V3 server-side validation
    public static async Task<bool> VerifyToken(string token)
    {
        try
        {
            var url = $"https://www.google.com/recaptcha/api/siteverify?secret={@System.Configuration.ConfigurationManager.AppSettings["ReCaptchaV3PrivateKey"]}&response={token}";

            using (var client = new HttpClient())
            {

                var httpResult = await client.GetAsync(url);

                var responseString2 = httpResult.Content.ReadAsStringAsync().Result;


                if (!httpResult.IsSuccessStatusCode)
                {
                    return false;
                }

                var googleResult = JsonConvert.DeserializeObject<CaptchaResponse>(responseString2);

                if (googleResult.Success && googleResult.Score >= 0.5)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        catch (Exception e)
        {
            return false;
        }
    }

}`

After all this, the form submits and a partial view is returned, but this appears on the view: System.Threading.Tasks.Task`1[System.Web.Mvc.ActionResult].

9
  • 1
    Why are you using Task.Factory.StartNew at all? Commented Apr 9, 2024 at 7:10
  • I can’t tell if your question is rhetorical or not. I’m going to assume you’re trying to be helpful. I’m using Task.Factory.StartNew because nothing else I tried worked. I’ve had a real issue getting these async methods to work on MVC3. Do you have a suggestion for what else I could try that would work for my very specific situation? Commented Apr 9, 2024 at 11:54
  • What is the target framework of the project? Can you provide a Minimal, Reproducible Example? Commented Apr 9, 2024 at 12:15
  • Framework is .NET 4. I spent a while trying to create a Minimal, Reproducible Example, but there are too many moving parts and I am already over on hours for this task. What I've provided is the best I can do with this. Thank you, either way. Commented Apr 9, 2024 at 14:54
  • @DayByDay the oldest supported .NET Framework version is 4.6.2. All versions since 4.5 support async/await and Task.Run. So, why are you using Task.Factory.StartNew, and why target something that reached End Of Life at least 8 years ago? Commented Apr 9, 2024 at 14:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.