Skip to main content

Quick Start

Get up and running with NetMediate in just a few minutes! This guide will walk you through creating a simple notification system.

🚀 Step 1: Install Packages​

First, install the required NuGet package:

dotnet add package NetMediate.Core
dotnet add package NetMediate.SourceGeneration

💡 Release productivity highlight

Use NetMediate.Core for contracts and NetMediate.SourceGeneration in the startup project. The generator package brings the runtime + required generators automatically.

Then open your .csproj and add the PackageReference:

<PackageReference Include="NetMediate.Core" Version="*" />
<PackageReference Include="NetMediate.SourceGeneration" Version="x.x.x.x">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>contentfiles; compile; runtime</PrivateAssets>
</PackageReference>
Library projects

Use the generator package with the explicit analyzer-style metadata:

<PackageReference Include="NetMediate.SourceGeneration" Version="x.x.x.x">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>contentfiles; compile; runtime</PrivateAssets>
</PackageReference>

🧩 Step 2: Define a Message​

Create a notification message. No marker interfaces are required - any class or record works:

namespace MyApp.Notifications;

public record UserCreated(string UserId, string Email, DateTime CreatedAt);

🛠️ Step 3: Create a Handler​

Create one or more handlers for your message:

using GenDI;
using NetMediate;

namespace MyApp.Handlers;

[ServiceInjection]
public interface IEmailService
{
Task SendWelcomeEmailAsync(string email, CancellationToken cancellationToken);
}

[Injectable(ServiceLifetime.Scoped)]
public sealed class EmailService : IEmailService
{
public Task SendWelcomeEmailAsync(string email, CancellationToken cancellationToken) =>
Task.CompletedTask;
}

[Injectable(ServiceLifetime.Scoped, Group = 100, Order = 1)]
public class WelcomeEmailHandler : INotificationHandler<UserCreated>
{
[Inject] public required IEmailService EmailService { get; init; }
[Inject] public required ILogger<WelcomeEmailHandler> Logger { get; init; }

public async Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
Logger.LogInformation(
"Sending welcome email to {Email} for user {UserId}",
notification.Email,
notification.UserId);

await EmailService.SendWelcomeEmailAsync(
notification.Email,
cancellationToken);
}
}

You can create multiple handlers for the same notification:

[ServiceInjection]
public interface IAuditService
{
Task LogAsync(string message, CancellationToken cancellationToken);
}

[Injectable(ServiceLifetime.Scoped)]
public sealed class AuditService : IAuditService
{
public Task LogAsync(string message, CancellationToken cancellationToken) => Task.CompletedTask;
}

[Injectable(ServiceLifetime.Scoped, Group = 100, Order = 2)]
public class AuditLogHandler : INotificationHandler<UserCreated>
{
[Inject] public required IAuditService AuditService { get; init; }

public async Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
await AuditService.LogAsync(
$"User {notification.UserId} was created",
cancellationToken);
}
}

⚙️ Step 4: Register Services​

Register NetMediate services in your application's startup/configuration:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NetMediate;

var builder = Host.CreateApplicationBuilder(args);

// The source generator discovers all handlers automatically
builder.Services.AddNetMediate();

// AddNetMediate also triggers AddGenDIServices(),
// so [Injectable] implementations are registered automatically.

var host = builder.Build();
await host.StartAsync();
tip

AddNetMediate() is generated at compile-time by the source generator. It automatically discovers and registers all handler implementations in your project - no manual registration needed!

GenDI style: prefer [Injectable] + [Inject]. With GenDI you can choose the service lifetime, Group, Order, and keyed registrations (Key). Use [Injectable<TService>] only when you need to force a specific non-generic contract and contract discovery does not already find [ServiceInjection]. Concrete non-generic classes that implement closed generic contracts can still use [Injectable]. Only generic/open service implementations (for example AuditBehavior<TMessage, TResponse>) should be registered manually in builder.Services for the AOT-oriented path.

📣 Step 5: Use the Mediator​

Inject IMediator and publish your notification:

using GenDI;
using NetMediate;

[Injectable(ServiceLifetime.Scoped)]
public class UserService
{
[Inject] public required IMediator Mediator { get; init; }
[Inject] public required IUserRepository UserRepository { get; init; }

public async Task<User> CreateUserAsync(
string email,
CancellationToken cancellationToken = default)
{
// Create the user
var user = new User { Email = email };
await UserRepository.AddAsync(user, cancellationToken);

// Publish the notification - all handlers will be invoked
await Mediator.Notify(
new UserCreated(user.Id, user.Email, DateTime.UtcNow),
cancellationToken);

return user;
}
}

✅ Complete Example​

Here's a complete minimal API example:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using NetMediate;
using GenDI;

var builder = WebApplication.CreateBuilder(args);

// Register NetMediate
builder.Services.AddNetMediate();

var app = builder.Build();

// Define the endpoint
app.MapPost("/users", async (CreateUserRequest request, IMediator mediator) =>
{
// Publish a notification
await mediator.NotifyUserCreatedAsync(new(
Guid.NewGuid().ToString(),
request.Email,
DateTime.UtcNow));

return Results.Ok(new { Message = "User created successfully" });
});

await app.RunAsync();

// Message types
public record CreateUserRequest(string Email);
public record UserCreated(string UserId, string Email, DateTime CreatedAt);

// Handler
[Injectable(ServiceLifetime.Scoped)]
public class UserCreatedHandler : INotificationHandler<UserCreated>
{
[Inject] public required ILogger<UserCreatedHandler> Logger { get; init; }

public Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
Logger.LogInformation(
"User created: {UserId}, {Email}",
notification.UserId,
notification.Email);

return Task.CompletedTask;
}
}

🔭 What's Next?​

Now that you have a working example, explore more features:

Troubleshooting​

AddNetMediate() not found​

If the AddNetMediate() method is not available:

  1. Ensure your startup project has a direct NetMediate.SourceGeneration package reference
  2. Rebuild your project
  3. Restart your IDE or refresh IntelliSense
  4. Check that your handler classes are not abstract or generic

Handlers not being called​

If your handlers aren't executing:

  1. Verify handlers implement the correct interface
  2. Ensure handlers are concrete (non-abstract) classes
  3. Check that you're using the correct mediator method (Notify, Send, Request, etc.)
  4. Enable logging to see mediator activity