/// <summary>
        /// Verifies reCAPTCHA response token and checks score (for v3) and action.
        /// </summary>
        /// <param name="context">A context for executing action.</param>
        /// <param name="next">A delegate that contains next action.</param>
        /// <returns></returns>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var recaptchaService = context.HttpContext.RequestServices.GetService <IRecaptchaService>();
            var recaptchaOptions = context.HttpContext.RequestServices.GetService <IOptions <RecaptchaOptions> >().Value;

            var remoteIp          = context.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
            var cancellationToken = recaptchaOptions.AttributeOptions.UseCancellationToken ?
                                    context.HttpContext.RequestAborted : CancellationToken.None;

            CheckResult checkResult = null;

            try
            {
                var recaptchaToken = context.GetResponseToken(recaptchaOptions.AttributeOptions);

                if (_score.HasValue)
                {
                    checkResult = await recaptchaService.VerifyAndCheckAsync(
                        new VerifyRequest()
                    {
                        Secret   = recaptchaOptions.SecretKey,
                        Response = recaptchaToken,
                        RemoteIp = remoteIp
                    },
                        _action,
                        _score.Value,
                        cancellationToken);
                }
                else
                {
                    checkResult = await recaptchaService.VerifyAndCheckAsync(
                        new VerifyRequest()
                    {
                        Secret   = recaptchaOptions.SecretKey,
                        Response = recaptchaToken,
                        RemoteIp = remoteIp
                    },
                        _action,
                        cancellationToken);
                }
            }
            catch (RecaptchaServiceException e)
            {
                HandleBadResult(context, recaptchaOptions, checkResult, e, null);
                return;
            }
            catch (Exception e)
            {
                HandleBadResult(context, recaptchaOptions, checkResult, null, e);
                return;
            }

            if (!checkResult.Success)
            {
                HandleBadResult(context, recaptchaOptions, checkResult, null, null);
                return;
            }

            await base.OnActionExecutionAsync(context, next);
        }