Skip to content

Latest commit

History

515 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

LicenseNuGetNuGet downloadsFuGetBuildCodeFactorGitHub repo size

EasyExtensions

EasyExtensions is a modular set of .NET packages for application code that tends to repeat across projects: core BCL extensions, ASP.NET Core helpers, PostgreSQL/EF Core setup, Quartz job registration, WebDAV clients, ImageSharp utilities, embedded fonts, streaming AES-GCM encryption, and a lightweight mediator.

The repository is intentionally split into small NuGet packages. Install only the package you need, keep your application dependencies narrow, and use the XML documentation in your IDE or FuGet when you need a full API reference.

Contents

Packages

PackageTargetUse when you need
EasyExtensionsnetstandard2.1Core extensions and helpers for strings, hashes, streams, enums, dates, IP/networking, claims, random strings, queues, password hashing abstractions, Brotli HTTP helpers, and stream cipher abstractions.
EasyExtensions.AnalyzersRoslynMaintainability rules for C# projects, including a hard 400-significant-line limit for source files.
EasyExtensions.AspNetCorenet10.0ASP.NET Core helpers for exception responses, health checks, CORS, request metadata, rate limiting helpers, console logging, controllers, form files, CPU usage, and PBKDF2 password hashing registration.
EasyExtensions.AspNetCore.Authorizationnet10.0JWT authentication setup, token creation, claim building, development authorization bypass, and a base auth controller with login, refresh, logout, password, and Google login hooks.
EasyExtensions.AspNetCore.Sentrynet10.0Sentry ASP.NET Core integration with user capture.
EasyExtensions.AspNetCore.Stacknet10.0One-call application setup for controllers, logging, compression, Quartz, SignalR, CORS, health checks, optional PostgreSQL, optional authorization, and optional EasyVault secrets.
EasyExtensions.Clientsnet10.0Cached IP lookup helpers backed by ipapi.co and configurable GeoIP endpoints.
EasyExtensions.Cryptonet10.0Streaming AES-GCM encryption/decryption, per-chunk authentication, HKDF subkeys, secure random bytes, and hash helpers.
EasyExtensions.Drawingnet10.0ImageSharp helpers for JPEG conversion, drawing text, blurred backgrounds, automatic brightness adjustment, and font integration.
EasyExtensions.EntityFrameworkCorenet10.0Audited entities and DbContext base types, Gridify mapper registration, database health checks, and migration helpers.
EasyExtensions.EntityFrameworkCore.Npgsqlnet10.0PostgreSQL DbContext registration, connection string construction from configuration, lazy loading options, and design-time factory registration.
EasyExtensions.Fontsnetstandard2.1Embedded fonts: Arial, Consola, FreeMonospaced, RetroGaming, and UbuntuMono.
EasyExtensions.Mediatornetstandard2.1A MediatR v12.5.0 based mediator package with request, notification, stream request, pipeline behavior, pre/post processor, and exception processor support.
EasyExtensions.Quartznetstandard2.1Reflection-based Quartz job registration with JobTriggerAttribute, hosted service setup, and optional PostgreSQL persistent store.
EasyExtensions.WebDavnetstandard2.1WebDAV and Nextcloud file operations: folders, existence checks, uploads, listings, downloads, and deletes.
EasyExtensions.Windowsnetstandard2.1Windows-specific helpers for shortcuts and moving files or directories to the recycle bin.

Installation

Install packages individually:

dotnet add package EasyExtensions
dotnet add package EasyExtensions.Analyzers
dotnet add package EasyExtensions.AspNetCore
dotnet add package EasyExtensions.Crypto
dotnet add package EasyExtensions.EntityFrameworkCore.Npgsql

For an opinionated ASP.NET Core setup, start with:

dotnet add package EasyExtensions.AspNetCore.Stack

The analyzer package enables the following build errors by default. Their severity is analyzer-owned, so dotnet_diagnostic.EEX*.severity entries cannot lower or disable them. Use a local #pragma warning disable EEXxxxx only for an explicitly approved exception:

RuleEnforces
EEX0001C# files stay within a hard maximum of 400 significant lines.
EEX0002The sealed keyword is not used.
EEX0003Each file contains one top-level class, record, interface, or enum, except a Mediator request with its handlers.
EEX0004Every EF Core relationship has a dependent navigation using [DeleteBehavior(DeleteBehavior.Restrict)].
EEX0005EF Core data models use data annotations instead of Fluent API when an annotation equivalent exists; value converters and shadow-property configuration remain allowed.
EEX0006Entities rooted in DbSet<T>, [Table], or an existing BaseEntity<T> graph derive from BaseEntity<T>, except explicit natural-key entities with [Key] and no conventional Id.
EEX0007*Dto types with a non-nullable value-type Id derive from BaseDto<T>.
EEX0008Concrete Quartz IJob implementations declare JobTriggerAttribute.
EEX0009EF Core raw SQL, Dapper query/execute APIs, and DbCommand.CommandText are not used, except constant CREATE EXTENSION IF NOT EXISTS setup through ExecuteSqlRawAsync.
EEX0010EF entity properties and fields do not end with Utc.
EEX0011Reflection discovery, activation, and invocation APIs require an explicit diagnostic suppression; runtime type names and Type.IsAssignableFrom are allowed.
EEX0012EF entity properties avoid business defaults: non-nullable strings, required byte arrays, and other reference values use null!; non-nullable collections may use []; nullable properties have no initializer.
EEX0013An enum is not duplicated by a same-named *Dto type.
EEX0014Local variables use explicit types, except where the inferred type is anonymous and cannot be named, plus the existing LINQ, tuple deconstruction, and visible generic construction exceptions.

Blank lines, comment-only lines, and generated files are excluded from EEX0001. The 400-line ceiling cannot be raised. max_lines may only set a stricter lower limit:

[*.cs]dotnet_code_quality.EEX0001.max_lines = 300

The package also applies its Microsoft SDK analyzer policy transitively: CA1849 and IDE0160 are errors, while IDE0290 and IDE0041 are warnings. It enables the latest SDK analysis level and build-time code-style enforcement automatically. Consuming projects may override these defaults in their own .editorconfig.

Quick Examples

Core Helpers

usingEasyExtensions.Extensions;usingEasyExtensions.Helpers;usingSystem.Net;stringdigest="hello".Sha512();IPAddressnetwork=IPAddress.Parse("192.168.10.25").GetNetwork(24);stringmaskedEmail=StringHelpers.HideEmail("vadim@example.com");

Clients

usingEasyExtensions.Clients;vardefaultGeoIp=awaitGeoIpClient.Shared.LookupAsync("8.8.8.8");varbridgeGeoIpClient=newGeoIpClient("https://bridge.cottoncloud.dev/api/v1/lookup");varbridgeGeoIp=awaitbridgeGeoIpClient.LookupAsync("8.8.8.8");

ASP.NET Core

usingEasyExtensions.AspNetCore.Extensions;builder.Logging.AddSimpleConsoleLogging();builder.Services.AddDefaultHealthChecks().AddDefaultCorsWithOrigins("https://app.example.com").AddExceptionHandler().AddPbkdf2PasswordHashService();

JWT Authorization

usingEasyExtensions.AspNetCore.Authorization.Extensions;builder.Services.AddJwt(useCookies:true);
{
"JwtSettings": {
"Key": "0123456789abcdef0123456789abcdef",
"Issuer": "my-api",
"Audience": "my-clients",
"LifetimeMinutes": 60
}
}

EasyStack

usingEasyExtensions.AspNetCore.Stack.Extensions;builder.AddEasyStack(stack =>stack.WithPostgres<AppDbContext>(useLazyLoadingProxies:false).AddAuthorization().UseSecrets(useSecrets:true));

PostgreSQL and EF Core

usingEasyExtensions.EntityFrameworkCore.Npgsql.Extensions;builder.Services.AddPostgresDbContext<AppDbContext>(postgres =>{postgres.ConfigurationSection="DatabaseSettings";postgres.UseLazyLoadingProxies=false;});
{
"DatabaseSettings": {
"Host": "localhost",
"Port": "5432",
"Username": "postgres",
"Password": "postgres",
"Database": "app"
}
}

Quartz Jobs

usingEasyExtensions.Quartz.Attributes;usingEasyExtensions.Quartz.Extensions;usingQuartz;[JobTrigger(minutes:5,startNow:true)]publicclassCleanupJob:IJob{publicTaskExecute(IJobExecutionContextcontext){returnTask.CompletedTask;}}builder.Services.AddQuartzJobs();

Streaming Encryption

usingEasyExtensions.Crypto;usingSystem.Security.Cryptography;byte[]masterKey=RandomNumberGenerator.GetBytes(AesGcmStreamCipher.KeySize);usingvarcipher=newAesGcmStreamCipher(masterKey,memoryLimitBytes:256L*1024*1024);awaitusingvarinput=File.OpenRead("plain.bin");awaitusingvarencrypted=File.Create("plain.bin.eegcm");awaitcipher.EncryptAsync(input,encrypted);awaitusingvarcipherText=File.OpenRead("plain.bin.eegcm");awaitusingvarplainText=File.Create("plain-restored.bin");awaitcipher.DecryptAsync(cipherText,plainText);

WebDAV and Nextcloud

usingEasyExtensions.WebDav;usingvarclient=WebDavCloudClient.CreateNextcloudClient("https://cloud.example.com",username:"user",password:"app-password");awaitclient.CreateFolderAsync("backups");usingvarbackup=File.OpenRead("backup.zip");awaitclient.UploadFileAsync(backup,"backups/backup.zip");

Configuration Notes

  • The full solution currently uses the .NET 10 SDK. Some packages still target netstandard2.1; see the package table before choosing a package for older applications.
  • EasyExtensions.AspNetCore.Authorization accepts either a JwtSettings section or flat JwtKey, JwtIssuer, JwtAudience, and JwtLifetimeMinutes keys. Configure a persistent signing key in production.
  • EasyExtensions.AspNetCore.Stack allows all CORS origins when CorsOrigins is missing. Set CorsOrigins explicitly for production services.
  • EasyExtensions.AspNetCore.Sentry enables SendDefaultPii when Sentry is active. Review this against your data handling policy.
  • EasyExtensions.Crypto expects you to own key storage and rotation. Do not hard-code master keys in source control.
  • EasyExtensions.WebDav currently changes ServicePointManager.ServerCertificateValidationCallback; review this before production use.

Build and Test

git clone https://github.com/bvdcode/EasyExtensions.git
cd EasyExtensions/Sources
dotnet restore
dotnet build --configuration Release
dotnet test --configuration Release

The test projects use NUnit and target net10.0.

Releases

Releases are produced by GitHub Actions from main when files under Sources/ change. The workflow builds the solution, packs NuGet packages, publishes artifacts, pushes packages to GitHub Packages and NuGet.org, and creates a GitHub release. Versioning is driven by GitVersion; the current next-version is configured in GitVersion.yml.

Contributing

Contributions are welcome. For a clean pull request:

  1. Fork the repository.
  2. Create a focused feature branch.
  3. Add or update tests for behavior changes.
  4. Run dotnet test from Sources/.
  5. Update this README when package scope, setup, or public examples change.
  6. Open a pull request with a clear description of the change.

Issues and feature requests are also welcome. Small, well-scoped proposals are easiest to review.

License

Most packages are distributed under the MIT License. See LICENSE.md.

EasyExtensions.Mediator is based on MediatR v12.5.0 and uses Apache-2.0 package licensing. See Sources/EasyExtensions.Mediator/LICENSE.md.

Contact

Created and maintained by Vadim Belov.

About

Extensions and methods that I use in my work every day, avoiding code duplication.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages