Four integration patterns — pick the one that fits your stack.
| # | Pattern | Server protection | Client-side | Best for | |
|---|---|---|---|---|---|
| 1 | ProtectedPaths middleware | ProtectedPaths in config; middleware intercepts before handler runs |
data-cwaptcha on form; cwaptcha.js hooks submit automatically |
Razor Pages / standard MVC forms — zero server code per action | Demo → |
| 2 | [CWaptchaValidation] + jQuery AJAX | [CWaptchaValidation] attribute on MVC controller action |
CWaptcha.sign(fields) → $.ajax({ data: signed }) |
Umbraco Surface Controllers; jQuery-based AJAX forms | Demo → |
| 3 | [CWaptchaValidation] + Vanilla Fetch | [CWaptchaValidation] attribute on MVC controller action |
CWaptcha.sign(fields) → fetch() with URLSearchParams |
Modern stacks with no jQuery dependency | Demo → |
| 4 | [CWaptchaValidation] + form submit | [CWaptchaValidation] attribute; no ProtectedPaths entry needed |
data-cwaptcha on form; browser POST to MVC controller |
MVC controller endpoints where per-action opt-in is preferred over global path config | Demo → |
| 5 | [CWaptchaValidation] + React SPA | [CWaptchaValidation] + host CORS policy (UseCors before UseCWaptcha) |
useCWaptcha(apiBase).submit(url, fields) from TestWeb/ClientApp |
SPA on a subdomain calling the API origin | Demo → |
// Pattern 1 — appsettings.json
"ProtectedPaths": [ "/Contact" ]
// form: <form method="post" data-cwaptcha>
// Pattern 2 — controller action
[HttpPost, CWaptchaValidation]
public IActionResult SaveForm(...) { ... }
// JS: CWaptcha.sign({ Name, Email }).then(signed => $.ajax({ data: signed, url: '...' }))
// Pattern 3 — same attribute, no jQuery
// JS: CWaptcha.sign(data).then(signed => fetch(url, { method:'POST', body: new URLSearchParams(signed) }))
// Pattern 4 — attribute + standard form submit
[HttpPost, CWaptchaValidation]
public IActionResult Submit(...) => Redirect("/done");
// form: <form method="post" action="/contact-mvc/submit" data-cwaptcha>