{"id":15039388,"url":"https://github.com/sqids/sqids-dotnet","last_synced_at":"2025-05-15T03:05:49.696Z","repository":{"id":176746963,"uuid":"658044547","full_name":"sqids/sqids-dotnet","owner":"sqids","description":"Official .NET port of Sqids. Generate short unique IDs from numbers.","archived":false,"fork":false,"pushed_at":"2025-03-11T13:37:42.000Z","size":137,"stargazers_count":930,"open_issues_count":1,"forks_count":24,"subscribers_count":16,"default_branch":"main","last_synced_at":"2025-04-11T14:17:58.006Z","etag":null,"topics":["csharp","dot-net","dotnet","hashids","id","id-generator","short-id","short-url","sqids","uid","unique-id","unique-id-generator"],"latest_commit_sha":null,"homepage":"https://sqids.org/dotnet","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqids.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-06-24T15:37:31.000Z","updated_at":"2025-04-09T12:19:36.000Z","dependencies_parsed_at":"2023-09-30T02:02:46.422Z","dependency_job_id":"39cebf04-df6c-4e57-999a-007b7875b43a","html_url":"https://github.com/sqids/sqids-dotnet","commit_stats":null,"previous_names":["sqids/sqids-dot-net","sqids/sqids-dotnet"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqids%2Fsqids-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqids%2Fsqids-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqids%2Fsqids-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqids%2Fsqids-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqids","download_url":"https://codeload.github.com/sqids/sqids-dotnet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dot-net","dotnet","hashids","id","id-generator","short-id","short-url","sqids","uid","unique-id","unique-id-generator"],"created_at":"2024-09-24T20:42:38.510Z","updated_at":"2025-05-15T03:05:49.676Z","avatar_url":"https://github.com/sqids.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://sqids.org/dotnet\"\u003e\n\t\t\u003cimg alt=\"Logo\" src=\"logo.svg\" /\u003e\n\t\u003c/a\u003e\n\u003c/p\u003e\n\u003ch1 align=\"center\"\u003eSqids .NET\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://www.nuget.org/packages/Sqids\"\u003e\n\t\t\u003cimg alt=\"Nuget\" src=\"https://img.shields.io/nuget/v/Sqids?style=for-the-badge\u0026logo=nuget\u0026color=008FF7\" /\u003e\n\t\u003c/a\u003e\n\t\u003ca href=\"https://www.nuget.org/packages/Sqids\"\u003e\n\t\t\u003cimg alt=\"Downloads\" src=\"https://img.shields.io/nuget/dt/Sqids?style=for-the-badge\" /\u003e\n\t\u003c/a\u003e\n\t\u003ca href=\"https://github.com/sqids/sqids-dotnet/releases\"\u003e\n\t\t\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/v/release/sqids/sqids-dotnet?style=for-the-badge\u0026color=FB0088\" /\u003e\n\t\u003c/a\u003e\n\t\u003ca href=\"https://github.com/sqids/sqids-dotnet/tree/main/src/Sqids\"\u003e\n\t\t\u003cimg alt=\"Language\" src=\"https://img.shields.io/badge/written_in-C%23-8F00FF?style=for-the-badge\" /\u003e\n\t\u003c/a\u003e\n\t\u003ca href=\"LICENSE\"\u003e\n\t\t\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/sqids/sqids-dotnet?style=for-the-badge\u0026color=FFA800\" /\u003e\n\t\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\tSqids (\u003cem\u003epronounced \"squids\"\u003c/em\u003e) is a small library that lets you generate YouTube-like IDs from numbers. It encodes numbers like \u003ccode\u003e127\u003c/code\u003e into strings like \u003ccode\u003eyc3\u003c/code\u003e, which you can then decode back into the original numbers. Sqids comes in handy when you want to obfuscate numbers (such as sequential numeric IDs) into random-looking strings, to be used in URLs and elsewhere.\n\u003c/p\u003e\n\n---\n\n## Features:\n\n-   💎 **Collision-free:** The IDs that Sqids generates are unique and can always be decoded back into the original numbers. You can also make them unique to your application (so that they're not the same as everyone else who uses Sqids) by providing a [shuffled alphabet](#custom-alphabet).\n-   🔢 **Multiple Numbers:** You can bundle more than one number into a single ID, and then decode the ID back into the same set of numbers.\n-   👁 **\"Eye-safe\":** Sqids makes sure that the IDs it generates do not contain common profanity, so you can safely use these IDs where end-users can see them (e.g. in URLs).\n-   🤹‍♀️ **Randomized Output:** Encoding sequential numbers (1, 2, 3...) yields completely different-looking IDs.\n-   💪 **Supports All Integral Types:** Powered by .NET 7's [generic math](https://learn.microsoft.com/en-us/dotnet/standard/generics/math) — you could use Sqids to encode/decode numbers of any integral numeric type in .NET, including `int`, `long`, `ulong`, `byte`, etc.\n-   ⚡ **Blazingly Fast:** With an optimized span-based implementation that minimizes memory allocation and maximizes performance.\n-   🔍 **Meticulously Tested:** Sqids has a comprehensive test suite that covers numerous edge cases, so you can expect a bug-free experience.\n-   ✅ **CLS-compliant:** Sqids can be used with any .NET language, not just C#. You can use Sqids just as easily with F#, for example.\n\n## Getting Started\n\nInstall the [NuGet package](https://nuget.org/packages/Sqids):\n\n```sh\nInstall-Package Sqids\n```\n\nAlternatively, using the .NET CLI:\n\n```sh\ndotnet add package Sqids\n```\n\n## Usage:\n\nAll you need is an instance of `SqidsEncoder`, which is the main class, responsible for both encoding and decoding.\n\nUsing the default parameterless constructor configures `SqidsEncoder` with the default options.\n\nIf you're using .NET 7 or greater, you need to specify the numeric type for the encoder — most commonly `int`:\n\n```csharp\nusing Sqids;\nvar sqids = new SqidsEncoder\u003cint\u003e();\n```\n\n\u003e **Note**\n\u003e You can use any [integral numeric type](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types) (e.g. `long`, `byte`, `short`, etc.) as the type argument. `int` is just the most common one, but if you need to encode/decode larger numbers, for example, you could use `long`/`ulong` instead.\n\nIf you're targeting an older framework than .NET 7, `SqidsEncoder` only supports `int`, and there is no generic type parameter you need to supply, so just:\n\n```cs\nvar sqids = new SqidsEncoder();\n```\n\n#### Single number:\n\n```cs\nvar id = sqids.Encode(1); // \"Uk\"\nvar number = sqids.Decode(id).Single(); // 1\n```\n\n#### Multiple numbers:\n\n```cs\nvar id = sqids.Encode(1, 2, 3); // \"86Rf07\"\nvar numbers = sqids.Decode(id); // [1, 2, 3]\n```\n\n\u003e **Note**\n\u003e Sqids also preserves the order when encoding/decoding multiple numbers.\n\n## Customizations:\n\nYou can easily customize the alphabet (the characters that Sqids uses to encode the numbers), the minimum length of the IDs (how long the IDs should be at minimum), and the blocklist (the words that should not appear in the IDs), by passing an instance of `SqidsOptions` to the constructor of `SqidsEncoder`.\n\nYou can specify all the properties, and any you leave out will fall back to their default values.\n\n#### Custom Alphabet:\n\nYou can give Sqids your own custom (ideally shuffled) alphabet to use in the IDs:\n\n```cs\nvar sqids = new SqidsEncoder\u003cint\u003e(new()\n{\n    // This is a shuffled version of the default alphabet, which includes lowercase letters (a-z), uppercase letters (A-Z), and digits (0-9)\n    Alphabet = \"mTHivO7hx3RAbr1f586SwjNnK2lgpcUVuG09BCtekZdJ4DYFPaWoMLQEsXIqyz\",\n});\n```\n\n\u003e **Note**\n\u003e It's recommended that you at least provide a shuffled alphabet when using Sqids — even if you want to use the same characters as those in the default alphabet — so that your IDs will be unique to you. You can use an online tool like [this one](https://codebeautify.org/shuffle-letters) to do that.\n\n\u003e **Note**\n\u003e The alphabet needs to be at least _3 characters_.\n\n#### Minimum Length:\n\nBy default, Sqids uses as few characters as possible to encode a given number. However, if you want all your IDs to be at least a certain length (e.g. for aesthetic reasons), you can configure this via the `MinLength` option:\n\n```cs\nvar sqids = new SqidsEncoder\u003cint\u003e(new()\n{\n    MinLength = 5,\n});\n```\n\n#### Custom Blocklist:\n\nSqids comes with a large default blocklist which will ensure that common curse words and such never appear anywhere in your IDs.\nYou can add extra items to this default blocklist like so:\n\n```cs\nvar sqids = new SqidsEncoder\u003cint\u003e(new()\n{\n    BlockList = { \"whatever\", \"else\", \"you\", \"want\" },\n});\n```\n\n\u003e **Note**\n\u003e Notice how the `new` keyword is omitted in the snippet above (yes, this is valid C#). This way the specified strings are \"added\" to the default blocklist, as opposed to overriding it — which is what would happen had you done `new() { ... }` (which you're also free to do if that's what you want).\n\n## Advanced Usage:\n\n#### Decoding a single number:\n\nIf you're decoding user-provided input and expect a single number, you can use C#'s pattern matching feature to perform the necessary check and extract the number in one go:\n\n```cs\nif (sqids.Decode(input) is [var singleNumber])\n{\n    // you can now use `singleNumber` (which is an `int`) however you wish\n}\n```\n\n\u003e **Note**\n\u003e This expression ensures that the decoded result is exactly one number, that is, not an empty array (which is what `Decode` returns when the input is invalid), and also not more than one number.\n\n#### Ensuring an ID is \"canonical\":\n\nDue to the design of Sqids's algorithm, decoding random strings (although only those that consist of characters found in the alphabet) can sometimes produce actual numbers. For example, with the default options, both `2fs` and `OSc` are decoded into the same number `3168` — even though if we try to encode `3168`, the result will be `OSc`, so `OSc` is the so-called \"canonical\" encoding of `3168`.\n\nAs you can probably imagine, this would be problematic in certain cases, such as when you're using these IDs as part of your URLs to identify resources; in such a case, the fact that more than one ID decodes into the same number means the same resource would be accessible via multiple different URLs, which is normally undesirable.\n\nThere is, however, a straightforward solution to this problem, which involves ensuring that the incoming ID is \"canonical\" before using its decoded value for further processing (e.g. doing a database lookup); and this can be done by simply re-encoding the decoded number(s) and making sure the result matches the original ID supplied by the client:\n\n```cs\nvar decoded = sqids.Decode(incomingId);\nbool isCanonical = incomingId == sqids.Encode(decoded); // If `incomingId` is `OSc`, this evaluates to `true` (because that's the canonical encoding of `3168`), and if `incomingId` is `2fs`, it evaluates to `false`.\n```\n\nYou can nicely combine this check with the check for a single number (the previous example) like so:\n\n```cs\nif (sqids.Decode(incomingId) is [var decodedId] \u0026\u0026\n    incomingId == sqids.Encode(decodedId))\n{\n    // `incomingId` decodes into a single number and is canonical, here you can safely proceed with the rest of the logic\n}\nelse\n{\n    // consider `incomingId` invalid — e.g. respond with 404\n}\n```\n\n#### Dependency injection:\n\nTo use `SqidsEncoder` with a dependency injection system, simply register it as a singleton service:\n\nWith default options:\n\n```cs\nservices.AddSingleton\u003cSqidsEncoder\u003cint\u003e\u003e();\n```\n\nWith custom options:\n\n```cs\nservices.AddSingleton(new SqidsEncoder\u003cint\u003e(new()\n{\n    Alphabet = \"ABCEDFGHIJ0123456789\",\n    MinLength = 6,\n}));\n```\n\nAnd then you can inject it anywhere you need it:\n\n```cs\npublic class SomeController(SqidsEncoder\u003cint\u003e sqids)\n{\n    // ...\n}\n```\n\n## License:\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqids%2Fsqids-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqids%2Fsqids-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqids%2Fsqids-dotnet/lists"}