Infolab.HashIds.TagHelpers
1.0.0-preview.5
dotnet add package Infolab.HashIds.TagHelpers --version 1.0.0-preview.5
NuGet\Install-Package Infolab.HashIds.TagHelpers -Version 1.0.0-preview.5
<PackageReference Include="Infolab.HashIds.TagHelpers" Version="1.0.0-preview.5" />
<PackageVersion Include="Infolab.HashIds.TagHelpers" Version="1.0.0-preview.5" />
<PackageReference Include="Infolab.HashIds.TagHelpers" />
paket add Infolab.HashIds.TagHelpers --version 1.0.0-preview.5
#r "nuget: Infolab.HashIds.TagHelpers, 1.0.0-preview.5"
#:package Infolab.HashIds.TagHelpers@1.0.0-preview.5
#addin nuget:?package=Infolab.HashIds.TagHelpers&version=1.0.0-preview.5&prerelease
#tool nuget:?package=Infolab.HashIds.TagHelpers&version=1.0.0-preview.5&prerelease
Infolab.HashIds
Turns integer identity values into short, non-sequential strings — 4242 becomes DbWgx6 — so database ids
don't leak out through URLs and JSON payloads. Backed by Sqids.
This is obfuscation, not encryption. It stops casual enumeration of /people/1, /people/2, /people/3;
it is not an access control mechanism.
Packages
| Package | Use it for |
|---|---|
| Infolab.HashIds.Core | The encoder, [HashIdProperty], and System.Text.Json converters. No ASP.NET dependency — safe to reference from DTO and application layers. |
| Infolab.HashIds.Mvc | Model binding for [HashIdParam] action parameters and the [HashIdRoute] filter. Applies to API and view controllers. |
| Infolab.HashIds.TagHelpers | Razor: asp-hashid-* on anchors and forms, hx-hashid-* for htmx. |
| Infolab.HashIds.Api | Result filter that hashes ids on the way out, plus an OpenAPI schema transformer so generated clients see string. |
Each builds on the one above it, so referencing Infolab.HashIds.Api brings Mvc and Core with it.
Getting started
dotnet add package Infolab.HashIds.Core
builder.Services.AddHashIds(builder.Configuration.GetSection(HashIdOptions.SectionName));
{
"HashIds": {
"Salt": "per-environment-secret",
"MinLength": 6
}
}
The salt is a secret — keep it in user secrets, environment variables or a key vault, not in source. Changing it changes every hash it produces, so ids already issued stop decoding.
Then annotate ids on your DTOs:
public class PersonDto
{
[HashIdProperty] public int Id { get; set; }
[HashIdProperty] public long? ParentId { get; set; }
}
{ "id": "DbWgx6", "parentId": "F9ktkaA" }
int, int?, long and long? are all supported, and a given value encodes identically at either
width — widening an id from int to long does not invalidate hashes already issued for it.
ASP.NET Core
Action parameters — mark the ones that are ids:
public async Task<IActionResult> Details([HashIdParam] int id) { ... }
Razor links — the referenced property must carry [HashIdProperty], which is checked at render time:
<a asp-controller="People" asp-action="Details" asp-hashid-id="PersonId">View</a>
<div hx-get hx-controller="People" hx-action="Details"
hx-hashid-id="PersonId" hx-target="#panel">Load</div>
The prefix is
asp-hashid-/hx-hashid-, notasp-route-hashid-. Anything nested under the built-inasp-route-/hx-route-prefixes gets bound by the built-in tag helper as well, which is a Razor compile error.
API results — when the result type lives in a layer that can't reference this library, register a projection instead of annotating it:
builder.Services.AddHashIdsApi(o =>
{
o.MapResult<CreateCommandResult>((r, h) =>
new HashIdEntityCreatedResult(h.Encode(r.Value), r.Succeeded, r.Errors));
});
builder.Services.AddOpenApi(o => o.AddSchemaTransformer<HashIdSchemaTransformer>());
Configuration
| Setting | Default | Notes |
|---|---|---|
Salt |
(none) | Shuffles the alphabet per deployment. Optional — leave empty to use Alphabet verbatim, which is how you stay compatible with an existing unsalted encoder. |
MinLength |
6 |
Shorter results are padded. |
Alphabet |
see below | Override to stay decode-compatible with hashes issued by a different encoder. |
The default alphabet omits i, I, l, o, O and 0 so hashes survive being read aloud or
transcribed.
Options are validated at startup (ValidateOnStart), so a bad alphabet fails the build-up rather
than the first request.
Notes
- Ids must be non-negative;
Encodethrows on a negative value. Decodereturnsnullfor anything that isn't a single valid value, including one that would overflowint— useDecodeLongfor ids that may exceedint.MaxValue.- Replacing the implementation is just a matter of registering your own
IHashIdService; decoration works too.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Htmx.TagHelpers (>= 1.12.0)
- Infolab.HashIds.Mvc (>= 1.0.0-preview.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-preview.5 | 78 | 7/26/2026 |
| 1.0.0-preview.4 | 59 | 7/26/2026 |
| 1.0.0-preview.3 | 64 | 7/26/2026 |