CheapHelpers.Networking
3.4.2
dotnet add package CheapHelpers.Networking --version 3.4.2
NuGet\Install-Package CheapHelpers.Networking -Version 3.4.2
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="CheapHelpers.Networking" Version="3.4.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CheapHelpers.Networking" Version="3.4.2" />
<PackageReference Include="CheapHelpers.Networking" />
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 CheapHelpers.Networking --version 3.4.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: CheapHelpers.Networking, 3.4.2"
#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 CheapHelpers.Networking@3.4.2
#: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=CheapHelpers.Networking&version=3.4.2
#tool nuget:?package=CheapHelpers.Networking&version=3.4.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
CheapHelpers
A collection of production-ready C# utilities, extensions, and services for .NET 11.0 development. Simplify common development tasks with battle-tested helpers for Blazor, Entity Framework, networking, email, PDF generation, billing, reporting, and more.
Packages
| Package | Version | Description |
|---|---|---|
| CheapHelpers | Core utilities, extensions, threading, and scheduling | |
| CheapHelpers.Models | Shared entities, DTOs, enums, and UBL invoice models | |
| CheapHelpers.EF | Entity Framework repository pattern with Identity support | |
| CheapHelpers.Services | Email, PDF, billing, reporting, notifications, auth, and integrations | |
| CheapHelpers.Blazor | Blazor components, account module, auth endpoints, and Hybrid features | |
| CheapHelpers.Networking | Network scanning, mDNS discovery, and device detection | |
| CheapHelpers.MAUI | MAUI platform implementations (iOS APNS, Android FCM) | |
| CheapHelpers.MediaProcessing | FFmpeg integration, hardware detection (Windows/Linux) | |
| CheapHelpers.Avalonia.Bridge | Desktop notification bridge for Avalonia apps |
Installation
# Core utilities and extensions
dotnet add package CheapHelpers
# Entity Framework repository pattern
dotnet add package CheapHelpers.EF
# Business services (email, PDF, billing, reporting, notifications)
dotnet add package CheapHelpers.Services
# Blazor components, account module, and Hybrid features
dotnet add package CheapHelpers.Blazor
# Network scanning and device discovery
dotnet add package CheapHelpers.Networking
Quick Start
String Extensions
using CheapHelpers.Extensions;
"hello world".Capitalize(); // "Hello world"
"0474123456".ToInternationalPhoneNumber(); // "+32474123456"
"Very long text here".TrimWithEllipsis(10); // "Very long ..."
"my:invalid*file".SanitizeFileName(); // "my_invalid_file"
Email Service (3 providers)
using CheapHelpers.Services.Email;
// MailKit (SMTP), Microsoft Graph, or SendGrid
var emailService = new SendGridEmailService(
fromName: "MyApp",
fromAddress: "noreply@myapp.com",
apiKey: "SG.xxx",
inDev: false,
developers: ["dev@myapp.com"]);
await emailService.SendEmailAsync(
"user@example.com", "Welcome!", "<h1>Welcome!</h1>",
attachments: [("invoice.pdf", pdfBytes)]);
Email Templates (Fluid/Liquid)
// Template data class
public class WelcomeEmailTemplateData : BaseEmailTemplateData
{
public override string Subject => $"Welcome, {UserName}!";
public string UserName { get; set; }
public string ActivationLink { get; set; }
}
// Render and send
var templateService = new EmailTemplateService(...);
var result = await templateService.RenderEmailAsync(new WelcomeEmailTemplateData
{
UserName = "John",
ActivationLink = "https://myapp.com/activate/abc123"
});
await emailService.SendEmailAsync("john@example.com", result.Subject, result.HtmlBody);
Notification System
// Register with multi-channel support
services.AddCheapNotifications<MyUser>(options =>
{
options.EnabledChannels = NotificationChannelFlags.InApp | NotificationChannelFlags.Email;
options.RealTimeProvider = "SignalR"; // Default. Use "RabbitMQ" for multi-server
});
// Blazor real-time (SignalR)
services.AddCheapNotificationsBlazor();
app.MapCheapNotificationsHub();
// Optional: RabbitMQ for cross-server delivery (SignalR stays client-facing)
services.AddCheapNotificationsRabbitMQConsumer("amqp://localhost");
API Key System
services.AddCheapApiKeys<MyUser>(options =>
{
options.KeyPrefix = "myapp_";
options.DefaultRateLimitPerMinute = 100;
});
// Generate — full key only returned once
var result = await apiKeyService.GenerateAsync(
userId, "Production API",
scopes: ["read", "write"],
prefixOverride: "VTQ_", // Per-call prefix override
expiresAt: DateTime.UtcNow.AddYears(1));
// result.FullKey = "VTQ_a7f3bc91..." (store immediately!)
// Validate
var validation = await apiKeyService.ValidateAsync(rawKey);
if (validation.IsValid)
Debug.WriteLine($"User: {validation.UserId}, Scopes: {string.Join(",", validation.Scopes)}");
Billing Service (Metered Usage)
services.AddCheapBilling<MyUser>(options =>
{
options.DefaultTaxRate = 21.00m; // Belgian VAT
options.InvoiceNumberPrefix = "INV";
});
// Record API usage (fire-and-forget safe)
await usageMeter.RecordUsageAsync(apiKeyId, "/api/data", "GET", 200, durationMs: 42);
// Generate invoice for a billing period
var invoice = await billingService.GenerateInvoiceAsync(
apiKeyId, billingPlanId,
new DateTime(2026, 3, 1), new DateTime(2026, 3, 31));
PEPPOL BIS 3.0 Invoicing
using CheapHelpers.Services.DataExchange.Ubl;
// Simple API — fluent builder, no UBL knowledge needed
var invoice = InvoiceBuilder.Create("INV-2026-000001")
.From("My Company", vatNumber: "BE0123456789")
.To("Acme Corp", vatNumber: "BE9876543210")
.DueIn(days: 30)
.AddLine("API calls - March 2026", quantity: 50000, unitPrice: 0.001m, vatPercent: 21)
.AddLine("Premium support", quantity: 1, unitPrice: 150.00m, vatPercent: 21)
.WithPayment(iban: "BE68539007547034", bic: "BBRUBEBB")
.Build();
// Tax totals, line totals, and monetary totals are calculated automatically
var invoiceService = new UblInvoiceService();
var xml = await invoiceService.CreateInvoiceXmlAsync(invoice);
// Credit notes work the same way
var creditNote = CreditNoteBuilder.Create("CN-2026-000001")
.CreditsInvoice("INV-2026-000001")
.WithReason("Overcharged API calls")
.From("My Company", vatNumber: "BE0123456789")
.To("Acme Corp", vatNumber: "BE9876543210")
.AddLine("API call correction", quantity: 10000, unitPrice: 0.001m, vatPercent: 21)
.Build();
// Advanced: use UblInvoice DTOs directly for full PEPPOL control
var advancedInvoice = new UblInvoice { /* full UBL model access */ };
Reporting Service
services.AddCheapReporting<MyUser>(options =>
{
options.StorageProvider = StorageProviderType.AzureBlob;
options.AzureBlobConnectionString = "...";
options.DefaultRetentionDays = 90;
});
// Generate PDF report
var result = await reportService.GenerateReportAsync(new ReportRequest<SalesRecord>
{
Name = "Monthly Sales",
Format = ReportFormat.Pdf,
Data = salesRecords,
Template = myPdfTemplate,
DistributeToEmails = ["manager@company.com"], // Auto-email after generation
RetentionDays = 30
});
// Download later
var (content, fileName, mimeType) = await reportService.DownloadReportAsync(result.ReportId);
Authentication (Multiple Providers)
// Plex SSO
services.AddPlexAuth(options => { options.AdminToken = "..."; });
app.MapPlexAuthEndpoints(); // /auth/plex-start, /auth/plex-callback, /auth/logout
// Google + Microsoft OAuth
services.AddGoogleAuth(options => { options.ClientId = "..."; options.ClientSecret = "..."; });
services.AddMicrosoftAuth(options => { options.ClientId = "..."; options.ClientSecret = "..."; });
// GitHub + Apple OAuth
services.AddGitHubAuth(options => { options.ClientId = "..."; });
services.AddAppleAuth(options => { options.TeamId = "..."; options.KeyId = "..."; });
// Optional: auto-provision CheapUser from external auth
services.AddExternalUserProvisioning<MyUser>();
Blazor Account Module
// Register services
services.AddCheapHelpersBlazor<MyUser>(options =>
{
options.UseEmailService<SendGridEmailService>();
options.AccountRouteOptions = new AccountRouteOptions
{
LoginRoute = "/auth/login",
};
});
// Consumer creates their own controller (one line):
[Route("Account/[action]")]
public class AccountController : CheapAccountController<MyUser>;
// Built-in pages: Login, Register, ForgotPassword, ResetPassword,
// ConfirmEmail, ConfirmEmailChange, SetPassword, ChangePassword,
// Authenticator (2FA), RecoveryCodes, PersonalData (GDPR), Lockout
// Account dashboard with extensible custom tabs
Entity Framework
// Generic context with Identity
services.AddCheapContext<MyUser>(options => options.UseSqlServer(connectionString))
.AddIdentity<IdentityRole>();
// Generic repository with pagination
public class ProductRepo<TUser>(IDbContextFactory<CheapContext<TUser>> factory)
: UserRepo<TUser>(factory) where TUser : CheapUser { }
var users = await userRepo.GetAllUsersPaginatedAsync(pageIndex: 1, pageSize: 20);
var stats = await userRepo.GetUserStatisticsAsync();
Scheduling
using CheapHelpers.Scheduling;
scheduledTaskService.RegisterDailyTask("cleanup", new TimeOnly(2, 0), async ct =>
{
await notificationService.DeleteExpiredAsync(ct);
});
scheduledTaskService.RegisterMonthlyTask("billing", 1, new TimeOnly(3, 0), async ct =>
{
await billingService.RunBillingCycleAsync(ct);
});
Network Scanning
services.AddNetworkScanning()
.AddAllDetectors() // UPnP, mDNS, HTTP, SSH
.AddJsonStorage();
var scanner = serviceProvider.GetRequiredService<INetworkScanner>();
scanner.DeviceDiscovered += (device) =>
Debug.WriteLine($"Found: {device.Name} ({device.IPv4Address})");
scanner.Start();
Project Structure
CheapHelpers/ Core utilities, extensions, scheduling, threading
CheapHelpers.Models/ Entities, DTOs, enums, UBL invoice models
CheapHelpers.EF/ Entity Framework, CheapContext, repositories
CheapHelpers.Services/
├── ApiKeys/ API key generation, validation, rate limiting
├── Auth/ IExternalAuthProvider, Plex SSO service
├── Billing/ Usage metering, invoice generation, billing cycles
├── DataExchange/
│ ├── Csv/ CSV import/export
│ ├── Excel/ Excel generation (ClosedXML)
│ ├── Json/ JSON file service
│ ├── Pdf/ PDF generation (iText) + optimization (iLovePDF)
│ ├── Ubl/ UBL Order/Invoice/CreditNote (UblSharp, PEPPOL BIS 3.0)
│ └── Xml/ XML serialization
├── Email/ MailKit, Microsoft Graph, SendGrid + Fluid templates
├── Geocoding/ Mapbox, Azure Maps, Google Maps, PTV Maps
├── Notifications/ Multi-channel (InApp, Email, SMS, Push) + RabbitMQ
├── Polling/ HTTP polling with exponential backoff
├── Reporting/ Report generation, storage, distribution, scheduling
└── Storage/ Azure Blob Storage
CheapHelpers.Blazor/
├── Components/ NotificationBell, CultureSelector
├── Extensions/ DI, Plex/OAuth/notification endpoint mapping
├── Helpers/ AuthenticatorHelper, AccountTabDefinition
├── Hybrid/ WebView bridge, push notifications, app bar
├── Middleware/ API key middleware
├── Pages/Account/ Full account module (login, register, 2FA, GDPR)
├── Services/ UserService, ExternalUserProvisioner, RabbitMQ consumer
└── Shared/ LoginDisplay, UploadFile, ImagePanel, Selectors
CheapHelpers.Networking/ Network scanner, mDNS discovery, device detectors
CheapHelpers.MediaProcessing/ FFmpeg integration, hardware detection (Win/Linux)
CheapHelpers.MAUI/ iOS APNS, Android FCM, status bar helpers
CheapHelpers.Avalonia.Bridge/ Desktop notification adapter
Key Dependencies
| Package | Used For |
|---|---|
| MailKit | SMTP email delivery |
| Microsoft.Graph | Microsoft Graph email |
| SendGrid | SendGrid email API |
| Fluid.Core | Liquid email templates |
| iText + iText.PdfOptimizer | PDF generation and optimization |
| ILove_PDF | Cloud PDF optimization |
| UblSharp | UBL 2.1 document generation (PEPPOL BIS 3.0) |
| RabbitMQ.Client | Cross-server notification transport |
| MudBlazor | Blazor UI components |
| ClosedXML | Excel file generation |
| Humanizer.Core | Relative timestamp formatting |
| FluentValidation | Form validation |
| Azure.Storage.Blobs | Report/file storage |
| Azure.Identity + Microsoft.Graph | Azure AD authentication |
| Microsoft.Azure.NotificationHubs | Push notification backend |
Requirements
- .NET 11.0 or later
- C# 15
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
git clone https://github.com/CheapNud/CheapHelpers.git
cd CheapHelpers
dotnet restore
dotnet build
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net11.0
- MeaMod.DNS (>= 1.0.71)
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.