Edi.Captcha
5.0.0
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package Edi.Captcha --version 5.0.0
NuGet\Install-Package Edi.Captcha -Version 5.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Edi.Captcha" Version="5.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Edi.Captcha" Version="5.0.0" />
<PackageReference Include="Edi.Captcha" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Edi.Captcha --version 5.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Edi.Captcha, 5.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Edi.Captcha@5.0.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Edi.Captcha&version=5.0.0
#tool nuget:?package=Edi.Captcha&version=5.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Edi.Captcha.AspNetCore
The Captcha module used in my blog
Install
NuGet Package Manager
Install-Package Edi.Captcha
or .NET CLI
dotnet add package Edi.Captcha
Session-Based Captcha (Traditional Approach)
1. Register in DI
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(20);
options.Cookie.HttpOnly = true;
});
services.AddSessionBasedCaptcha();
// Don't forget to add this line in your `Configure` method.
app.UseSession();
or you can customize the options
services.AddSessionBasedCaptcha(option =>
{
option.Letters = "2346789ABCDEFGHJKLMNPRTUVWXYZ";
option.SessionName = "CaptchaCode";
option.CodeLength = 4;
});
2. Generate Image
Using MVC Controller
private readonly ISessionBasedCaptcha _captcha;
public SomeController(ISessionBasedCaptcha captcha)
{
_captcha = captcha;
}
[Route("get-captcha-image")]
public IActionResult GetCaptchaImage()
{
var s = _captcha.GenerateCaptchaImageFileStream(
HttpContext.Session,
100,
36
);
return s;
}
Using Middleware
app.UseSession().UseCaptchaImage(options =>
{
options.RequestPath = "/captcha-image";
options.ImageHeight = 36;
options.ImageWidth = 100;
});
3. Add CaptchaCode Property to Model
[Required]
[StringLength(4)]
public string CaptchaCode { get; set; }
5. View
<div class="col">
<div class="input-group">
<div class="input-group-prepend">
<img id="img-captcha" src="~/captcha-image" />
</div>
<input type="text"
asp-for="CommentPostModel.CaptchaCode"
class="form-control"
placeholder="Captcha Code"
autocomplete="off"
minlength="4"
maxlength="4" />
</div>
<span asp-validation-for="CommentPostModel.CaptchaCode" class="text-danger"></span>
</div>
6. Validate Input
_captcha.ValidateCaptchaCode(model.CommentPostModel.CaptchaCode, HttpContext.Session)
To make your code look more cool, you can also write an Action Filter like this:
public class ValidateCaptcha : ActionFilterAttribute
{
private readonly ISessionBasedCaptcha _captcha;
public ValidateCaptcha(ISessionBasedCaptcha captcha)
{
_captcha = captcha;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var captchaedModel =
context.ActionArguments.Where(p => p.Value is ICaptchable)
.Select(x => x.Value as ICaptchable)
.FirstOrDefault();
if (null == captchaedModel)
{
context.ModelState.AddModelError(nameof(captchaedModel.CaptchaCode), "Captcha Code is required");
context.Result = new BadRequestObjectResult(context.ModelState);
}
else
{
if (!_captcha.Validate(captchaedModel.CaptchaCode, context.HttpContext.Session))
{
context.ModelState.AddModelError(nameof(captchaedModel.CaptchaCode), "Wrong Captcha Code");
context.Result = new ConflictObjectResult(context.ModelState);
}
else
{
base.OnActionExecuting(context);
}
}
}
}
and then
services.AddScoped<ValidateCaptcha>();
and then
public class YourModelWithCaptchaCode : ICaptchable
{
public string YourProperty { get; set; }
[Required]
[StringLength(4)]
public string CaptchaCode { get; set; }
}
[ServiceFilter(typeof(ValidateCaptcha))]
public async Task<IActionResult> SomeAction(YourModelWithCaptchaCode model)
{
// ....
}
Stateless Captcha (Recommended for Scalable Applications)
Advantages of Stateless Captcha:
- ✅ Works in clustered/load-balanced environments
- ✅ No server-side session storage required
- ✅ Built-in expiration through encryption
- ✅ Secure token-based validation
- ✅ Better scalability
- ✅ Single API call for both token and image
1. Register in DI
services.AddStatelessCaptcha();
or with custom options:
services.AddStatelessCaptcha(options =>
{
options.Letters = "2346789ABCDGHKMNPRUVWXYZ";
options.CodeLength = 4;
options.TokenExpiration = TimeSpan.FromMinutes(5);
});
2. Create Model with Token Support
public class StatelessHomeModel
{
[Required]
[StringLength(4)]
public string CaptchaCode { get; set; }
public string CaptchaToken { get; set; }
}
3. Example Controller
using Edi.Captcha.SampleApp.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Diagnostics;
namespace Edi.Captcha.SampleApp.Controllers;
public class StatelessController(IStatelessCaptcha captcha) : Controller
{
public IActionResult Index()
{
return View(new StatelessHomeModel());
}
[HttpPost]
public IActionResult Index(StatelessHomeModel model)
{
if (ModelState.IsValid)
{
bool isValidCaptcha = captcha.Validate(model.CaptchaCode, model.CaptchaToken);
return Content(isValidCaptcha ? "Success - Stateless captcha validated!" : "Invalid captcha code");
}
return BadRequest();
}
[Route("get-stateless-captcha")]
public IActionResult GetStatelessCaptcha()
{
var result = captcha.GenerateCaptcha(100, 36);
return Json(new {
token = result.Token,
imageBase64 = Convert.ToBase64String(result.ImageBytes)
});
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
4. Example View
@model StatelessHomeModel
@{
ViewData["Title"] = "Stateless Captcha Example";
}
<div class="text-center">
<h1 class="display-4">Stateless Captcha Example</h1>
<p>This example shows how to use stateless captcha that works in clustered environments.</p>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="card">
<div class="card-header">
<h5>Stateless Captcha Form</h5>
</div>
<div class="card-body">
<form asp-action="Index" method="post" id="stateless-form">
<div class="form-group mb-3">
<label>Captcha Image:</label>
<div class="d-flex align-items-center">
<img id="captcha-image" src="" alt="Captcha" class="me-2" style="border: 1px solid #ccc;" />
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="refreshCaptcha()">
🔄 Refresh
</button>
</div>
<small class="form-text text-muted">Click refresh to get a new captcha</small>
</div>
<div class="form-group mb-3">
<label asp-for="CaptchaCode">Enter Captcha Code:</label>
<input asp-for="CaptchaCode" class="form-control" placeholder="Enter the code from image" autocomplete="off" />
<span asp-validation-for="CaptchaCode" class="text-danger"></span>
</div>
<input type="hidden" asp-for="CaptchaToken" id="captcha-token" />
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
<a asp-controller="Home" asp-action="Index" class="btn btn-secondary">Session-based Example</a>
</div>
</form>
<div class="mt-4">
<h6>Advantages of Stateless Captcha:</h6>
<ul class="small">
<li>✅ Works in clustered/load-balanced environments</li>
<li>✅ No server-side session storage required</li>
<li>✅ Built-in expiration through encryption</li>
<li>✅ Secure token-based validation</li>
<li>✅ Better scalability</li>
<li>✅ Single API call for both token and image</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<script>
async function refreshCaptcha() {
try {
const response = await fetch('/get-stateless-captcha');
const data = await response.json();
// Set the token for validation
document.getElementById('captcha-token').value = data.token;
// Set the image source using base64 data
document.getElementById('captcha-image').src = `data:image/png;base64,${data.imageBase64}`;
// Clear the input
document.getElementById('CaptchaCode').value = '';
} catch (error) {
console.error('Error refreshing captcha:', error);
alert('Failed to load captcha. Please try again.');
}
}
// Initialize captcha on page load
document.addEventListener('DOMContentLoaded', function() {
refreshCaptcha();
});
</script>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- SixLabors.ImageSharp (>= 3.1.11)
- SixLabors.ImageSharp.Drawing (>= 2.1.7)
-
net9.0
- SixLabors.ImageSharp (>= 3.1.11)
- SixLabors.ImageSharp.Drawing (>= 2.1.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Edi.Captcha:
| Repository | Stars |
|---|---|
|
EdiWang/Moonglade
Blog system of https://edi.wang, runs on Microsoft Azure
|
| Version | Downloads | Last Updated |
|---|---|---|
| 6.0.0 | 47 | 3/15/2026 |
| 5.3.0 | 1,659 | 11/13/2025 |
| 5.2.1 | 245 | 10/31/2025 |
| 5.2.0 | 268 | 10/14/2025 |
| 5.1.1 | 201 | 10/4/2025 |
| 5.1.0 | 153 | 10/3/2025 |
| 5.0.1 | 161 | 10/3/2025 |
| 5.0.0 | 324 | 10/3/2025 |
| 4.0.0 | 546 | 8/17/2025 |
| 3.26.4 | 354 | 7/31/2025 |
| 3.26.3 | 387 | 7/2/2025 |
| 3.26.2 | 445 | 6/6/2025 |
| 3.26.1 | 1,173 | 3/11/2025 |
| 3.26.0 | 499 | 2/8/2025 |
| 3.25.0 | 1,613 | 11/13/2024 |
| 3.24.0 | 1,550 | 8/11/2024 |
| 3.23.1 | 790 | 7/14/2024 |
| 3.23.0 | 313 | 7/8/2024 |
| 3.22.0 | 1,127 | 5/19/2024 |
| 3.21.2 | 1,534 | 3/11/2024 |
Loading failed