CloudEvents nos proporciona un conjunto consistente de metadatos que se pueden incluir en los eventos de una aplicación Event-Driven. En resumen: es un standar para este tipo de desarrollos.

No es más que un JSON, como el que muestro:

{
    "specversion" : "1.0",
    "type" : "[your_type]",
    "source" : "[your_source]",
    "subject" : "[your_subject]",
    "id" : "[your_id]",
    "time" : "2022-08-18T21:00:00Z",
    "datacontenttype" : "application/cloudevents+json",
    "data" : "{\"name\":\"Your_JSON_Data\", \"description\":\"Some JSON example\"}"
}

No existe una forma común de definir eventos. Esta especificación abierta nos permite portabilidad e interoperativididad entre sistemas.

Tal y como he mostrado en el ejemplo, los atributos anteriores son parte de la definición; algunos son requeridos y otros son opcionales.

En el proyecto de GitHub, podrás encontrar detallada la definición: ver este enlace.

Existen SDK para C# (donde tenemos una carpeta sample) o bien un NuGet.

Por ejemplo si quieres crear un Azure Event Grid con CloudEvents:

az eventgrid domain event-subscription create -n es2 \
    -g rg1 --domain-name domain1 \
    --endpoint https://contoso.azurewebsites.net/api/f1?code=code \
    --event-delivery-schema cloudeventschemav1_0

Publicamos un evento:

var topicEndpoint = new Uri("[your_azure_endpoint]");
var credential = new AzureKeyCredential("[you_azure_key]");
var publisher = new EventGridPublisherClient(topicEndpoint, credential);

var source = "[your_source]";
var type = "[your_type]";
var dataContentType = "application/cloudevents+json";
var data = new SampleData() { name = "your_Name", surname = "your_surname" };
    
var @event = new CloudEvent(source, type, data, dataContentType);
var events = new List<CloudEvent>() { @event };
    
await publisher.SendEventsAsync(events);

Y lo consumimos en una function:

[FunctionName("HttpTriggerCSharp")]
public static async Task Run(
 [HttpTrigger(AuthorizationLevel.Anonymous, "post", 
 Route = "[your_route]")] HttpRequest req,
 ILogger log)
  {
    using (var reader = new StreamReader(req.Body))
    {
      var payload = await reader.ReadToEndAsync();
      var events = CloudEvent.Parse(payload);    
      foreach (var @event in events)
            {
              var data = await @event.GetDataAsync<SampleData>();
            }
        }    
        return new OkResult();
    }

He dejado los ejemplos muy simplificados para que se entienda lo esencial.

Espero que este pequeño artículo os muestre como hacer eventos de forma consistente y evitar crear eventos muy específicos que te obliguen a meter mucha lógica extra, que habitualmente se debe al desconocimiento de lo que son los eventos en este tipo de arquitectura.