PMQ.Notifications 1.0.6

dotnet add package PMQ.Notifications --version 1.0.6
                    
NuGet\Install-Package PMQ.Notifications -Version 1.0.6
                    
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="PMQ.Notifications" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PMQ.Notifications" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="PMQ.Notifications" />
                    
Project file
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 PMQ.Notifications --version 1.0.6
                    
#r "nuget: PMQ.Notifications, 1.0.6"
                    
#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 PMQ.Notifications@1.0.6
                    
#: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=PMQ.Notifications&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=PMQ.Notifications&version=1.0.6
                    
Install as a Cake Tool

PMQ.Notifications

A package for managing notifications and business rules in .NET applications, making it easy to handle messages, errors, and domain rules in a centralized and strongly-typed way.
Designed to fit CQRS, MediatR, and DDD patterns, enabling clear separation of concerns.

NuGet
License: MIT


Installation

Install via NuGet:

dotnet add package PMQ.Notifications

Or manually add the reference in your .csproj.


How it works

The package provides a notification context (INotificationContext) to register, query, and handle business rule violations, not found errors, or any kind of custom notification, using strongly-typed notification types (NotificationType).

Main components

  • INotificationContext: Abstraction for managing notifications.
  • NotificationContext: Default implementation of INotificationContext.
  • Notification: Represents a single notification (key, message, type).
  • NotificationType: Enum-like value object for message categorization.

Usage Examples

Registering the service

builder.Services.AddScoped<INotificationContext, NotificationContext>();

Command + Handler with Mediator (business rule example)

In this scenario we want to add a product to a category.

  • If the category does not exist → a notification is added.
  • If the product already exists in the category → a business rule notification is added.
using MediatR;
using PMQ.Notifications;

public record AddProductCommand(string CategoryId, string ProductName) : IRequest<bool>;

public class AddProductCommandHandler : IRequestHandler<AddProductCommand, bool>
{
    private readonly INotificationContext _notifications;
    private readonly ICategoryRepository _categoryRepository;

    public AddProductCommandHandler(
        INotificationContext notifications,
        ICategoryRepository categoryRepository)
    {
        _notifications = notifications;
        _categoryRepository = categoryRepository;
    }

    public async Task<bool> Handle(AddProductCommand request, CancellationToken cancellationToken)
    {
        var category = await _categoryRepository.GetByIdAsync(request.CategoryId, cancellationToken);

        if (category is null)
        {
            _notifications.Add("Category", $"Category with id '{request.CategoryId}' was not found.", NotificationType.NotFound);
            return false;
        }

        if (category.Products.Any(p => p.Name.Equals(request.ProductName, StringComparison.OrdinalIgnoreCase)))
        {
            _notifications.Add("Product", $"The product '{request.ProductName}' already exists in this category.", NotificationType.BusinessRule);
            return false;
        }

        //Business rule passed → add product
        category.AddProduct(request.ProductName);

        await _categoryRepository.UpdateAsync(category, cancellationToken);

        return true;
    }
}

Querying notifications in application layer

if (_notifications.HasType(NotificationType.NotFound))
{
    var notFoundMessages = _notifications.GetMessages(NotificationType.NotFound);
    // handle not found logic
}

if (_notifications.HasType(NotificationType.BusinessRule))
{
    var businessRuleErrors = _notifications.GetMessages(NotificationType.BusinessRule);
    // handle business rule violation
}

if (_notifications.HasNotifications)
{
    var allMessages = _notifications.GetMessages();
    // handle all notifications
}

Clearing notifications

_notifications.Clear();

Usage in Filters (with ResultExecutingContext)

In API projects, you can use a filter to automatically map notifications into HTTP responses.

public class NotificationFilter : IResultFilter
{
    private readonly INotificationContext _context;

    public NotificationFilter(INotificationContext context) => _context = context;

    public void OnResultExecuting(ResultExecutingContext context)
    {
        if (_context.HasType(NotificationType.Validation))
        {
            context.Result = new BadRequestObjectResult(_context.GetMessages(NotificationType.Validation));
        }
        else if (_context.HasType(NotificationType.NotFound))
        {
            context.Result = new NotFoundObjectResult(_context.GetMessages(NotificationType.NotFound));
        }
        else if (_context.HasNotifications)
        {
            context.Result = new UnprocessableEntityObjectResult(_context.GetMessages());
        }
    }

    public void OnResultExecuted(ResultExecutedContext context) { }
}

Register globally:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<NotificationFilter>();
});

Benefits of using NotificationContext

  • Separation of concerns: business rules and not-found checks are decoupled from controllers and services.
  • Consistency: all rule violations and messages are centralized.
  • Testability: easy to assert domain notifications in unit tests.
  • Extensibility: custom notification types can be added (e.g., Security, AccessDenied).

Keywords for Discoverability

These keywords help developers and AI tools to find this package on NuGet and GitHub:

notifications, validation, business-rules, ddd, domain-driven-design, cqrs, mediator, mediatR, clean-architecture, error-handling, result-pattern, notification-pattern, application-layer, domain-events


MIT License © 2025 Pablo Mickael Quevedo

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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
1.0.6 123 8/31/2025
1.0.4 59 8/3/2025
1.0.0 61 8/3/2025