I thought I would have a go at using Blazor server-side, and so far I've managed to overcome most headaches one way or another and enjoyed it, until now.
I'm trying to write a validator for Google Recaptcha v3, which requires a users IP address. Usually I would just get the IHttpContextAccessor with:
var httpContextAccessor = (IHttpContextAccessor)validationContext.GetService(typeof(IHttpContextAccessor));
But that now returns null! I also found that trying to get IConfiguration in the same way failed, but for that, I could just make a static property in Startup.cs.
This is the last hurdle in a days work, and it's got me baffled.
Any ideas on how to get that IP address into a validator?
Thanks!
Edit:
I just found the error making httpContextAccessor null!
((System.RuntimeType)validationContext.ObjectType).DeclaringMethodthrew an exception of type 'System.InvalidOperationException'
this is the validator:
public class GoogleReCaptchaValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Lazy<ValidationResult> errorResult = new Lazy<ValidationResult>(() => new ValidationResult("Google reCAPTCHA validation failed", new String[] { validationContext.MemberName }));
if (value == null || String.IsNullOrWhiteSpace(value.ToString()))
{
return errorResult.Value;
}
var configuration = Startup.Configuration;
string reCaptchResponse = value.ToString();
string reCaptchaSecret = configuration["GoogleReCaptcha:SecretKey"];
IHttpContextAccessor httpContextAccessor = validationContext.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("secret", reCaptchaSecret),
new KeyValuePair<string, string>("response", reCaptchResponse),
new KeyValuePair<string, string>("remoteip", httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString())
});
HttpClient httpClient = new HttpClient();
var httpResponse = httpClient.PostAsync("https://www.google.com/recaptcha/api/siteverify", content).Result;
if (httpResponse.StatusCode != HttpStatusCode.OK)
{
return errorResult.Value;
}
String jsonResponse = httpResponse.Content.ReadAsStringAsync().Result;
dynamic jsonData = JObject.Parse(jsonResponse);
if (jsonData.success != true.ToString().ToLower())
{
return errorResult.Value;
}
return ValidationResult.Success;
}
}