Demo 3 — [CWaptchaValidation] + Vanilla fetch()

Same [CWaptchaValidation] attribute as Demo 2, but the client uses the native fetch() API instead of jQuery. No jQuery dependency required.

How it works: CWaptcha.sign(data) returns a plain object with all CAPTCHA fields merged in. Encode it as URLSearchParams and POST it as application/x-www-form-urlencoded — the same format Request.Form reads on the server.

Active CWaptcha settings (demo info panel)
Cooldown120s base → ×2 per retry during lockout → capped at 3600s
Challenge fallbackBypassBehavior, window 120s, tolerance 6px
Min fill time3000 ms
Require mouse movementTrue
Anomaly trigger threshold0.75
Response modeTooManyRequests429
Behavior memory TTL3600 s
Honeypot fieldcw_hp_email
Nonce TTL300 s

A behavior_flagged rejection right after a successful submit means the cooldown above is active — each retry during the lockout extends it. Wait it out (the AJAX/fetch demos show the remaining seconds), or lower CWaptcha:Behavior:CooldownSeconds in appsettings.json while testing.






Show client-side code
document.getElementById('fetchForm').addEventListener('submit', function (e) {
    e.preventDefault();
    var data = {
        Name:    document.getElementById('fname').value,
        Email:   document.getElementById('femail').value,
        Message: document.getElementById('fmsg').value
    };
    CWaptcha.sign(data)
        .then(function (signed) {
            return fetch('/api/contact-fetch/submit', {
                method:  'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body:    new URLSearchParams(signed).toString()
            });
        })
        .then(function (resp) {
            return resp.json().then(function (body) {
                return { ok: resp.ok, body: body };
            });
        })
        .then(function (r) {
            var el = document.getElementById('result');
            if (r.ok) {
                el.innerHTML = '<strong>Received via fetch()!</strong><p>' + r.body.name + ' — ' + r.body.email + '</p>';
                el.style.borderColor = 'green';
            } else {
                el.textContent = 'Error: ' + (r.body.failureReason || 'unknown');
                el.style.borderColor = 'red';
            }
            el.style.display = 'block';
        })
        .catch(function (err) {
            var el = document.getElementById('result');
            el.textContent = 'CWaptcha error: ' + err.message;
            el.style.borderColor = 'red';
            el.style.display = 'block';
        });
});