A MediatR bridge for Azure Event Grid.
You can install the latest version of MediatR.Azure.EventGrid
from NuGet by running the following command in PowerShell:
Install-Package MediatR.Azure.EventGrid
Alternatively, you can use the .NET command line:
dotnet add package MediatR.Azure.EventGrid
To use EventGridMediator
, you need to register it with the IServiceCollection
along with MediatR:
services
.AddMediatR(mediator => mediator.RegisterServicesFromAssembly(typeof(Program).Assembly))
.AddEventGridMediator();
This will automatically deserialize the Event Grid system topics data.
For custom events, you need to register each data type:
- For
EventGridEvent
objects, theEventType
andDataVersion
properties are used to resolve the .NET type. - For
CloudEvent
objects, theType
andDataSchema
properties are used to resolve the .NET type.
To register a custom data type, use the DataTypes.Add
method on the EventGridMediatorBuilder
:
services.AddEventGridMediator(builder =>
{
builder.DataTypes
.Add<MyCustomEventData>(nameof(MyCustomEventData))
.Add<MyCustomEventDataV2>(nameof(MyCustomEventData), "2.0");
});
Alternatively, you can use the EventGridDataTypeAttribute
attribute on classes to register them through assembly discovery of public types:
services.AddEventGridMediator(builder => builder.DataTypes.RegisterFromAssembly(typeof(Program).Assembly));
[EventGridDataType(nameof(MyCustomEventData))]
public class MyCustomEventData
{
}
To publish EventGridEvent
objects using the EventGridMediator
, use the following code (the example is an ASP.NET Core Minimal API):
app.MapPost("/api/events", async (HttpContext context, CancellationToken cancellationToken) =>
{
var json = await BinaryData.FromStreamAsync(context.Request.Body, cancellationToken).ConfigureAwait(false);
var events = EventGridEvent.ParseMany(json);
var mediator = context.RequestServices.GetRequiredService<EventGridMediator>();
await mediator.PublishAsync(events, cancellationToken);
});
To publish CloudEvent
objects, use the following code (the example is an ASP.NET Core Minimal API):
app.MapPost("/api/events", async (HttpContext context, CancellationToken cancellationToken) =>
{
var json = await BinaryData.FromStreamAsync(context.Request.Body, cancellationToken).ConfigureAwait(false);
var events = CloudEvent.ParseMany(json);
var mediator = context.RequestServices.GetRequiredService<EventGridMediator>();
await mediator.PublishAsync(events, cancellationToken);
});
If you don't want to have a dependency on the MediatR
package, you can still publish events to Event Grid by using the MediatR.Azure.EventGrid.Serialization
package on its own.
To publish EventGridEvent
objects using the default serializer used by EventGridMediator
to resolve the data type, use the following code (the example is an ASP.NET Core Minimal API):
app.MapPost("/api/endpoint", async (HttpContext context, CancellationToken cancellationToken) =>
{
var eventData = new MyCustomEventData();
var factory = context.RequestServices.GetRequiredService<EventGridEventFactory>();
var client = context.RequestServices.GetRequiredService<EventGridPublisherClient>();
var eventGridEvent = factory.Create("subject", eventData);
await client.SendEventAsync(eventGridEvent, cancellationToken);
});
public record MyCustomEventData { }
To publish `CloudEvent objects, use the following code (the example is an ASP.NET Core Minimal API):
app.MapPost("/api/endpoint", async (HttpContext context, CancellationToken cancellationToken) =>
{
var eventData = new MyCustomEventData();
var factory = context.RequestServices.GetRequiredService<CloudEventFactory>();
var client = context.RequestServices.GetRequiredService<EventGridPublisherClient>();
var cloudEvent = factory.Create("source", eventData);
await client.SendEventAsync(cloudEvent, cancellationToken);
});
public record MyCustomEventData { }
By default, MediatR will invoke each INotificationHandler<T>
sequentially. However, as of MediatR 12.0.0, you can now parallelize the notification with the TaskWhenAllPublisher
strategy. For more information, see pull request 838.
Regardless of the notification strategy you choose, keep in mind that handlers should be idempotent because any failures may require reprocessing of the event.
To handle EventGridEvent
objects, implement IEventGridEventHandler<T>
:
public record MyCustomEventData { }
public class MyCustomEventHandler : IEventGridEventHandler<MyCustomEventData>
{
public Task HandleAsync(EventGridEvent eventGridEvent, MyCustomEventData data, CancellationToken cancellationToken)
{
Debug.WriteLine($"Received event {eventGridEvent.Id} of type {eventGridEvent.EventType} with data {data}.");
return Task.CompletedTask;
}
}
To handle CloudEvent
objects, implement ICloudEventHandler<T>
:
public record MyCustomEventData { }
public class MyCustomEventHandler : ICloudEventHandler<MyCustomEventData>
{
public Task HandleAsync(CloudEvent cloudEvent, MyCustomEventData data, CancellationToken cancellationToken)
{
Debug.WriteLine($"Received event {cloudEvent.Id} of type {cloudEvent.Type} with data {data}.");
return Task.CompletedTask;
}
}