Simple Google ReCaptcha validation Linked:
Google reCAPTCHA Validator: Iteration II



I have also created a simple Google Recaptcha Validation class to handle verification.  

I used some code from CodingFusion's post Google New reCaptcha I am not a robot using asp .net, but I have altered it so that it fit my use case, and to make it extendable and reusable.

Can I clean it up further? 

public class ReCaptchaValidator
{
    private readonly string _ReCaptchaSecret;
    private readonly string _ReCaptchaSiteKey;
    public List&lt;string&gt; ErrorCodes { get; set; }

    public ReCaptchaValidator(string reCaptchaSecret)
    {
        _ReCaptchaSecret = reCaptchaSecret;
        this.ErrorCodes = new List&lt;string&gt;();
    }
    public ReCaptchaValidator(string reCaptchaSecret, string reCaptchaSiteKey)
    {
        _ReCaptchaSecret = reCaptchaSecret;
        _ReCaptchaSiteKey = reCaptchaSiteKey;
        this.ErrorCodes = new List&lt;string&gt;();
    }

    public bool ValidateCaptcha(HttpRequest request)
    {
        var sb = new StringBuilder();
        sb.Append("https://www.google.com/recaptcha/api/siteverify?secret=");
        sb.Append(_ReCaptchaSecret);
        sb.Append("&amp;response=");
        sb.Append(request.Form["g-recaptcha-response"]);

        //client ip address
        sb.Append("&amp;remoteip=");
        sb.Append(GetUserIp(request));

        //make the api call and determine validity
        using (var client = new WebClient())
        {
            var uri = sb.ToString();
            var json = client.DownloadString(uri);
            var serializer = new DataContractJsonSerializer(typeof(RecaptchaApiResponse));
            var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
            var result = serializer.ReadObject(ms) as RecaptchaApiResponse;

            if (result == null)
            {
                return false;
            }
            else if (result.ErrorCodes != null)
            {
                foreach(var code in result.ErrorCodes)
                {                        
                    this.ErrorCodes.Add(code.ToString());
                }
                return false;
            }
            else if (!result.Success)
            {
                return false;
            }
            else //-- If successfully verified.
            {
                return true;
            }
        }
    }

    //--- To get user IP(Optional)
    private string GetUserIp(HttpRequest request)
    {
        var visitorsIpAddr = string.Empty;

        if (request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
        {
            visitorsIpAddr = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
        }
        else if (!string.IsNullOrEmpty(request.UserHostAddress))
        {
            visitorsIpAddr = request.UserHostAddress;
        }
        return visitorsIpAddr;
    }

}
[DataContract]
public class RecaptchaApiResponse
{
    [DataMember(Name = "success")]
    public bool Success;

    [DataMember(Name = "error-codes")]
    public List&lt;string&gt; ErrorCodes;
}
private readonly string _ReCaptchaSecret;
private readonly string _ReCaptchaSiteKey;


private fields are either lowerCamelCase or _lowerCamelCase, both conventions are common.



public ReCaptchaValidator(string reCaptchaSecret)
{
    _ReCaptchaSecret = reCaptchaSecret;
    this.ErrorCodes = new List&lt;string&gt;();
}
public ReCaptchaValidator(string reCaptchaSecret, string reCaptchaSiteKey)
{
    _ReCaptchaSecret = reCaptchaSecret;
    _ReCaptchaSiteKey = reCaptchaSiteKey;
    this.ErrorCodes = new List&lt;string&gt;();
}


Don't repeat work in your constructors: use chaining instead.

public ReCaptchaValidator(string reCaptchaSecret)
{
    _ReCaptchaSecret = reCaptchaSecret;
    this.ErrorCodes = new List&lt;string&gt;();
}

public ReCaptchaValidator(string reCaptchaSecret, string reCaptchaSiteKey) 
    : this (reCaptchaSecret)
{
    _ReCaptchaSiteKey = reCaptchaSiteKey;
}




With C# 6, you can also use a property initializer to.. initialize.. your property.

public List&lt;string&gt; ErrorCodes { get; set; }

public ReCaptchaValidator(string reCaptchaSecret)
{
    _ReCaptchaSecret = reCaptchaSecret;
    this.ErrorCodes = new List&lt;string&gt;();
}


becomes

public List&lt;string&gt; ErrorCodes { get; set; } = new List&lt;string&gt;();

public ReCaptchaValidator(string reCaptchaSecret)
{
    _ReCaptchaSecret = reCaptchaSecret;
}




I would also advise to use a private setter for your ErrorCodes like this:

public List&lt;string&gt; ErrorCodes { get; private set; } = new List&lt;string&gt;();


Likewise, with C# 6, you might as well make it a readonly property:

public List&lt;string&gt; ErrorCodes { get; } = new List&lt;string&gt;();




StringBuilders see their most use when you're concatenating strings in a loop. In this scenario I would use a formatted string which turns this:

var sb = new StringBuilder();
sb.Append("https://www.google.com/recaptcha/api/siteverify?secret=");
sb.Append(_ReCaptchaSecret);
sb.Append("&amp;response=");
sb.Append(request.Form["g-recaptcha-response"]);
sb.Append("&amp;remoteip=");
sb.Append(GetUserIp(request));


into this:

var uri = string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&amp;response={1}&amp;remoteip={2}",
    _ReCaptchaSecret, 
    request.Form["g-recaptcha-response"], 
    GetUserIp(request));


Or with C# 6:

var uri = $"https://www.google.com/recaptcha/api/siteverify?secret={_ReCaptchaSecret}&amp;response={(request.Form["g-recaptcha-response"])}&amp;remoteip={GetUserIp(request)}";




else if (!string.IsNullOrEmpty(request.UserHostAddress))


I prefer string.IsNullOrWhiteSpace because only rarely whitespace characters are considered good input.