dotnet add package CWaptcha
Never commit SecretKey to source control. Use user-secrets in development and environment variables in production.
# Development
dotnet user-secrets set "CWaptcha:SecretKey" "your-32-char-minimum-secret-here"
# Production (IIS — set in system environment variables or web.config)
CWaptcha__SecretKey=your-secret-here
{
"CWaptcha": {
"LicenseKey": "CW-...", // from CWaptcha.KeyGen
"Domain": "example.com", // must match the licensed domain
"NonceTtlSeconds": 300,
"HoneypotFieldName": "cw_hp_email",
"ProtectedPaths": [ "/Contact" ],
"RequireHttps": true
}
}
List the POST routes you want the middleware to intercept automatically in ProtectedPaths. Leave it empty if you're using [CWaptchaValidation] on controller actions instead.
Keep LicenseKey out of source control — use user-secrets (dev) or an environment variable (CWaptcha__LicenseKey) in production. Without a key, CWaptcha logs a warning but still protects forms.
using CWaptcha.AspNetCore.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCWaptcha(builder.Configuration.GetSection("CWaptcha"));
var app = builder.Build();
app.UseStaticFiles();
app.UseCWaptcha(); // ← before MapRazorPages / MapControllers
app.MapRazorPages();
app.Run();
<!-- Add data-cwaptcha to the form you want to protect -->
<form method="post" data-cwaptcha>
<input name="Name" required />
<input name="Email" type="email" required />
<button type="submit">Send</button>
</form>
<!-- Include cwaptcha.js before </body> -->
<script src="/cwaptcha/cwaptcha.js" data-honeypot="cw_hp_email"></script>
That's it. The middleware will intercept the POST, validate the CAPTCHA, and pass valid requests through to your handler. Invalid requests receive a 400 response automatically.
public class ContactModel : PageModel
{
[BindProperty] public string Name { get; set; } = "";
[BindProperty] public string Email { get; set; } = "";
public void OnGet() { }
public void OnPost()
{
// Only ever reached if CWaptcha passed validation
}
}