DevSource.Stack.Notifications
3.0.0
See the version list below for details.
dotnet add package DevSource.Stack.Notifications --version 3.0.0
NuGet\Install-Package DevSource.Stack.Notifications -Version 3.0.0
<PackageReference Include="DevSource.Stack.Notifications" Version="3.0.0" />
<PackageVersion Include="DevSource.Stack.Notifications" Version="3.0.0" />
<PackageReference Include="DevSource.Stack.Notifications" />
paket add DevSource.Stack.Notifications --version 3.0.0
#r "nuget: DevSource.Stack.Notifications, 3.0.0"
#:package DevSource.Stack.Notifications@3.0.0
#addin nuget:?package=DevSource.Stack.Notifications&version=3.0.0
#tool nuget:?package=DevSource.Stack.Notifications&version=3.0.0
<div align="center">
<img src="https://github.com/uitanmaciel/devsource-stack-notifications/blob/main/src/DevSource.Stack.Notifications/devsource-icon.jpeg"
width="130"
/>
</div>
DevSource.Stack.Notifications
This library is an implementation for application-level Notifications, designed to facilitate error handling and validation in a systematic and flexible way, allowing the developer to avoid throwing exceptions throughout the system. It allows errors and messages to be accumulated throughout the process flow, enabling a cohesive response mechanism.
DevSource.Stack.Notifications is an integral part of the DevSource ecosystem.
Features
- Validation Rules: Comprehensive validation rules for strings, numbers, dates, emails, passwords, documents, phones, collections, credit cards, and files
- Notification Pattern: Implement the Notification Pattern to avoid throwing exceptions throughout your application
- Fluent API: Chainable validation methods for clean and readable code
- Custom Messages: Support for custom error messages on all validations
- Brazilian Document Validation: Built-in support for CPF and CNPJ validation
- Phone Validation: Support for Brazilian and international phone formats
- Collection Validation: Validate collections and enumerables with ease
- Credit Card Validation: Luhn algorithm implementation for credit card validation
- File Validation: Validate file sizes, extensions, and MIME types
- Conditional Validation: Execute validations conditionally with When, RequireAtLeastOne, and AllOrNone
- Type-Safe: Generic implementation with strong typing support
- Lightweight: Zero external dependencies, pure .NET implementation
- Well-Tested: Comprehensive test suite with 130+ tests ensuring reliability
Requirements
- .NET 8.0 or higher
- No external dependencies required
Getting Started
Installation
Install the package from NuGet:
dotnet add package DevSource.Stack.Notifications
Basic Setup
Inherit from Notifier class in your domain entities or services:
using DevSource.Stack.Notifications;
public class User : Notifier
{
public string Name { get; set; } = null!;
public string Email { get; set; } = null!;
public string Password { get; set; } = null!;
}
Usage Examples
Basic Validation
using DevSource.Stack.Notifications;
using DevSource.Stack.Notifications.Validations;
public class User : Notifier
{
public string Name { get; set; } = null!;
public string Email { get; set; } = null!;
public string Password { get; set; } = null!;
public User(string name, string email, string password)
{
Name = name;
Email = email;
Password = password;
}
public Task<bool> Create()
{
ValidateFields();
if (HasNotifications) // Check for validation errors
return Task.FromResult(false);
// Business logic to create user
return Task.FromResult(true);
}
private void ValidateFields()
{
AddNotifications(new ValidationRules<User>()
.IsNotNull(nameof(Name), Name)
.MinLength(nameof(Name), Name, 3)
.IsEmail(nameof(Email), Email)
.IsPassword(nameof(Password), Password, 8)
);
}
}
Handling Notifications
Check the Notifications property to capture validation errors:
var user = new User("John Doe", "invalid-email", "short");
var result = await user.Create();
if (result)
{
Console.WriteLine("User created successfully!");
}
else
{
foreach (var notification in user.Notifications)
{
Console.WriteLine($"{notification.Key}: {notification.Message}");
}
}
Output:
Email: The 'Email' is not a valid email
Password: The value of field 'Password' is invalid
Custom Error Messages
You can provide custom error messages for any validation:
AddNotifications(new ValidationRules<User>()
.IsNotNull(nameof(Name), Name, "Name is required")
.MinLength(nameof(Name), Name, 3, "Name must have at least 3 characters")
.IsEmail(nameof(Email), Email, "Please provide a valid email address")
);
String Validations
AddNotifications(new ValidationRules<Product>()
.IsNotNull(nameof(Name), Name)
.MinLength(nameof(Name), Name, 3)
.MaxLength(nameof(Name), Name, 100)
.MinLength(nameof(Description), Description, 10)
);
Number Validations
AddNotifications(new ValidationRules<Product>()
.IsGreaterThan(nameof(Price), Price, 0)
.IsLowerThan(nameof(Discount), Discount, 100)
.IsBetween(nameof(Stock), Stock, 0, 1000)
);
DateTime Validations
AddNotifications(new ValidationRules<Event>()
.IsInTheFuture(nameof(StartDate), StartDate)
.IsDateBetween(nameof(EndDate), EndDate, DateTime.Now, DateTime.Now.AddYears(1))
.IsDayOfWeek(nameof(StartDate), StartDate, DayOfWeek.Monday)
);
Brazilian Document Validations
AddNotifications(new ValidationRules<Customer>()
.IsCpf(nameof(Cpf), Cpf) // Validates CPF format and check digits
.IsCnpj(nameof(Cnpj), Cnpj) // Validates CNPJ format and check digits
);
Phone Validations
AddNotifications(new ValidationRules<Contact>()
.IsBrazilianPhone(nameof(Phone), Phone) // (XX) XXXXX-XXXX
.IsInternationalPhone(nameof(InternationalPhone), InternationalPhone) // +55XXXXXXXXXXX
);
Collection Validations
AddNotifications(new ValidationRules<Order>()
.IsNotEmpty(nameof(Items), Items)
.HasMinItems(nameof(Items), Items, 1)
.HasMaxItems(nameof(Items), Items, 10)
.HasExactItems(nameof(Items), Items, 5)
.HasUniqueItems(nameof(Tags), Tags)
.ContainsItem(nameof(Categories), Categories, "Electronics")
);
Credit Card Validations
AddNotifications(new ValidationRules<Payment>()
.IsCreditCard(nameof(CardNumber), CardNumber) // Luhn algorithm
.IsCreditCardNotExpired(nameof(ExpiryDate), ExpiryMonth, ExpiryYear)
);
File Validations
| Method | Description | Example |
|---|---|---|
HasMaxFileSize(key, size, maxSize) |
Validates file size limit | .HasMaxFileSize("File", size, 5_000_000) |
HasValidExtension(key, fileName, extensions) |
Validates file extension | .HasValidExtension("File", name, ".jpg", ".png") |
HasValidMimeType(key, mimeType, allowedTypes) |
Validates MIME type | .HasValidMimeType("File", type, "image/jpeg") |
Conditional Validations
| Method | Description | Example |
|---|---|---|
When(condition, action) |
Executes validations when condition is true | .When(isActive, r => r.IsNotNull("Name", name)) |
When(conditionFunc, action) |
Executes validations when function returns true | .When(() => age < 18, r => r.IsNotNull(...)) |
RequireAtLeastOne(params values) |
Validates at least one value is not null/empty | .RequireAtLeastOne(email, phone, address) |
AllOrNone(params values) |
Validates all values are filled or all are empty | .AllOrNone(state, city, zipCode) |
Conditional Validations
AddNotifications(new ValidationRules<User>()
.When(user.IsCompany, rules => rules
.IsNotNull(nameof(CompanyName), CompanyName)
.IsCnpj(nameof(Cnpj), Cnpj))
.When(() => user.Age < 18, rules => rules
.IsNotNull(nameof(ParentName), ParentName))
.RequireAtLeastOne(Email, Phone) // At least one must be filled
.AllOrNone(State, City, ZipCode) // All or none must be filled
);
Combining Multiple Validators
You can combine validations from different notifiers:
var addressValidator = new ValidationRules<Address>()
.IsNotNull(nameof(Street), address.Street)
.IsNotNull(nameof(City), address.City);
var userValidator = new ValidationRules<User>()
.IsNotNull(nameof(Name), Name)
.IsEmail(nameof(Email), Email)
.Join(addressValidator); // Combine validations
AddNotifications(userValidator);
API Reference
Available Validations
String Validations
| Method | Description | Example |
|---|---|---|
IsNotNull(key, value) |
Validates that string is not null or empty | .IsNotNull("Name", name) |
MinLength(key, value, minLength) |
Validates minimum string length | .MinLength("Name", name, 3) |
MaxLength(key, value, maxLength) |
Validates maximum string length | .MaxLength("Name", name, 100) |
Number Validations
| Method | Description | Example |
|---|---|---|
IsGreaterThan(key, value, comparer) |
Validates number is greater than specified value | .IsGreaterThan("Price", price, 0) |
IsLowerThan(key, value, comparer) |
Validates number is lower than specified value | .IsLowerThan("Discount", discount, 100) |
IsBetween(key, value, from, to) |
Validates number is within range | .IsBetween("Age", age, 18, 65) |
Supports: int, double, decimal
DateTime Validations
| Method | Description | Example |
|---|---|---|
IsInTheFuture(key, value) |
Validates date is in the future | .IsInTheFuture("EventDate", date) |
IsInThePast(key, value) |
Validates date is in the past | .IsInThePast("BirthDate", date) |
IsDateBetween(key, value, from, to) |
Validates date is within range | .IsDateBetween("Date", date, start, end) |
IsDayOfWeek(key, value, dayOfWeek) |
Validates specific day of week | .IsDayOfWeek("Date", date, DayOfWeek.Monday) |
Email & Password Validations
| Method | Description | Example |
|---|---|---|
IsEmail(key, value) |
Validates email format | .IsEmail("Email", email) |
IsPassword(key, value, minLength) |
Validates password strength | .IsPassword("Password", pass, 8) |
Core Classes
Notifier
Base class that provides notification management capabilities:
public class Notifier
{
public IReadOnlyCollection<Notification> Notifications { get; }
public bool HasNotifications { get; }
protected void AddNotification(Notification notification)
protected void AddNotifications(IEnumerable<Notification> notifications)
protected void AddNotifications(params Notifier[] notifiers)
protected void ClearNotifications()
}
ValidationRules<T>
Fluent validation builder:
public class ValidationRules<T> : Notifier
{
public ValidationRules<T> Join(params Notifier[] notifiers)
// All validation methods return ValidationRules<T> for chaining
}
Notification
Represents a single notification:
public class Notification
{
public string Key { get; }
public string Message { get; }
}
Integration with ASP.NET Core
Minimal API Example
app.MapPost("/users", async (CreateUserRequest request) =>
{
var user = new User(request.Name, request.Email, request.Password);
var result = await user.Create();
if (!result)
return Results.BadRequest(new { errors = user.Notifications });
return Results.Created($"/users/{user.Id}", user);
});
Controller Example
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateUserRequest request)
{
var user = new User(request.Name, request.Email, request.Password);
var result = await user.Create();
if (!result)
return BadRequest(new { errors = user.Notifications });
return CreatedAtAction(nameof(GetById), new { id = user.Id }, user);
}
}
Custom Validation Middleware
public class NotificationMiddleware
{
private readonly RequestDelegate _next;
public NotificationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (ValidationException ex)
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsJsonAsync(new
{
errors = ex.Notifications
});
}
}
}
Running the tests
To run the tests, use the following command:
dotnet test
To run with coverage:
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Uitan Maciel - GitHub Profile
<div align="center"> Made with ❤️ by the DevSource community </div>
| 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 was computed. 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. |
-
net8.0
- No dependencies.
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 | |
|---|---|---|---|
| 4.0.0 | 143 | 2/20/2026 | |
| 3.0.1 | 187 | 1/31/2026 | |
| 3.0.0 | 298 | 12/15/2025 | |
| 2.0.0 | 320 | 6/17/2025 | |
| 1.0.10 | 293 | 4/9/2025 | |
| 1.0.9 | 244 | 11/29/2024 | |
| 1.0.8 | 227 | 9/16/2024 | |
| 1.0.6 | 200 | 9/10/2024 | |
| 1.0.5 | 206 | 9/10/2024 | |
| 1.0.4 | 218 | 9/1/2024 | |
| 1.0.3 | 235 | 9/1/2024 | |
| 1.0.2 | 201 | 8/3/2024 | |
| 1.0.1 | 194 | 7/29/2024 | |
| 1.0.0 | 196 | 7/25/2024 |
Version 3.0.0 is a major update focused on expanding validation capabilities and improving flexibility.
### Breaking Changes
- The `Notifier` class is no longer `abstract`, allowing it to be inherited by `record` types.
- The overloads for `RequireAtLeastOne` and `AllOrNone` that accepted a custom message have been removed to resolve a method signature conflict with `params`.
### New Features
- **60+ New Validation Methods:** Massively expanded the validation library.
- **Brazilian Document Validation:** Added `IsCpf()` and `IsCnpj()` with full digit validation.
- **Phone Number Validation:** Added `IsBrazilianPhone()` and `IsInternationalPhone()`.
- **Collection Validations:** New methods like `IsNotEmpty()`, `HasMinItems()`, `HasMaxItems()`, `HasExactItems()`, `HasUniqueItems()`, and `ContainsItem()`.
- **Credit Card Validation:** Added `IsCreditCard()` (Luhn algorithm) and `IsCreditCardNotExpired()`.
- **File Validation:** Added `HasMaxFileSize()`, `HasValidExtension()`, and `HasValidMimeType()`.
- **Conditional Validation:** Added `When()`, `RequireAtLeastOne()`, and `AllOrNone()` for complex validation logic.
- **Expanded String Validations:** Added 12 new methods, including `IsUrl()`, `IsAlphabetic()`, `IsAlphanumeric()`, `IsNumeric()`, `MatchesPattern()`, `StartsWith()`, `EndsWith()`, `IsUpperCase()`, `IsLowerCase()`, and more.
- **Record Support:** `Notifier` can now be directly inherited by `record` types.
### Other
- **Increased Test Coverage:** Added over 90 new unit tests, bringing the total to 130+ and ensuring high reliability.
- **Updated Documentation:** The `README.md` has been completely overhauled with examples for all new validations and a comprehensive API reference.