An open API service indexing awesome lists of open source software.

https://github.com/smokedlinq/aemediator

A MediatR bridge for Azure Event Grid
https://github.com/smokedlinq/aemediator

azure csharp dotnet eventgrid mediatr

Last synced: 8 months ago
JSON representation

A MediatR bridge for Azure Event Grid

Awesome Lists containing this project

README

          

# Azure Event Grid Mediator

---

![CI](https://github.com/smokedlinq/aemediator/workflows/CI/badge.svg)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=smokedlinq_aemediator&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=smokedlinq_aemediator)
[![NuGet](https://img.shields.io/nuget/dt/MediatR.Azure.EventGrid.svg)](https://www.nuget.org/packages/MediatR.Azure.EventGrid)
[![NuGet](https://img.shields.io/nuget/vpre/MediatR.Azure.EventGrid.svg)](https://www.nuget.org/packages/MediatR.Azure.EventGrid)

A [MediatR](/jbogard/MediatR) bridge for Azure Event Grid.

## Installing MediatR.Azure.EventGrid

You can install the latest version of `MediatR.Azure.EventGrid` from NuGet by running the following command in PowerShell:

```powershell
Install-Package MediatR.Azure.EventGrid
```

Alternatively, you can use the .NET command line:

```dotnetcli
dotnet add package MediatR.Azure.EventGrid
```

## Getting Started

To use `EventGridMediator`, you need to register it with the `IServiceCollection` along with MediatR:

```csharp
services
.AddMediatR(mediator => mediator.RegisterServicesFromAssembly(typeof(Program).Assembly))
.AddEventGridMediator();
```

This will automatically deserialize the [Event Grid system topics](https://learn.microsoft.com/azure/event-grid/system-topics) data.

## Custom Events

For custom events, you need to register each data type:

- For `EventGridEvent` objects, the `EventType` and `DataVersion` properties are used to resolve the .NET type.
- For `CloudEvent` objects, the `Type` and `DataSchema` properties are used to resolve the .NET type.

To register a custom data type, use the `DataTypes.Add` method on the `EventGridMediatorBuilder`:

```csharp
services.AddEventGridMediator(builder =>
{
builder.DataTypes
.Add(nameof(MyCustomEventData))
.Add(nameof(MyCustomEventData), "2.0");
});
```

Alternatively, you can use the `EventGridDataTypeAttribute` attribute on classes to register them through assembly discovery of public types:

```csharp
services.AddEventGridMediator(builder => builder.DataTypes.RegisterFromAssembly(typeof(Program).Assembly));

[EventGridDataType(nameof(MyCustomEventData))]
public class MyCustomEventData
{
}
```

## Publishing Events to MediatR

To publish `EventGridEvent` objects using the `EventGridMediator`, use the following code (the example is an ASP.NET Core Minimal API):

```csharp
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();

await mediator.PublishAsync(events, cancellationToken);
});
```

To publish `CloudEvent` objects, use the following code (the example is an ASP.NET Core Minimal API):

```csharp
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();

await mediator.PublishAsync(events, cancellationToken);
});
```

## Publishing Events to Event Grid

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):

```csharp
app.MapPost("/api/endpoint", async (HttpContext context, CancellationToken cancellationToken) =>
{
var eventData = new MyCustomEventData();
var factory = context.RequestServices.GetRequiredService();
var client = context.RequestServices.GetRequiredService();
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):

```csharp
app.MapPost("/api/endpoint", async (HttpContext context, CancellationToken cancellationToken) =>
{
var eventData = new MyCustomEventData();
var factory = context.RequestServices.GetRequiredService();
var client = context.RequestServices.GetRequiredService();
var cloudEvent = factory.Create("source", eventData);

await client.SendEventAsync(cloudEvent, cancellationToken);
});

public record MyCustomEventData { }
```

## Handling Events

By default, MediatR will invoke each `INotificationHandler` 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](https://github.com/jbogard/MediatR/pull/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`:

```csharp
public record MyCustomEventData { }

public class MyCustomEventHandler : IEventGridEventHandler
{
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`:

```csharp
public record MyCustomEventData { }

public class MyCustomEventHandler : ICloudEventHandler
{
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;
}
}
```