This project provides a set of .NET tools for the management of subscriptions to events, basic transformations and notifications of such event occurrences (webhooks): in a global design scope, this model enables event-driven architectures, triggering system processes upon the occurrence of expected occurrences from other systems.
Although this integration model is widely adopted by major service providers (like SendGrid, Twilio, GitHub, Slack, etc.), there is no formal protocol or authority that would enforce a compliance (like for other cases, such as OpenID, OpenAPI, etc.).
Anyway, a typical implementation consists of the following elements:
- Webhooks are transported through HTTP POST callbacks
- The webhook payload is formatted as a JSON object (or alternatively, in lesser common scenarios, as XML or Form)
- The webhook payload includes properties that describe the type of event and the time-stamp of the occurrence
- An optional signature in the header of the request or a query-string parameter ensures the authenticity of the caller
I tried to express the concepts in more detail in this page within this repository (without any ambition to be pedagogic).
The libraries currently provided by the framework are the following:
The following libraries extend the framework with receivers for specific providers:
Library | NuGet | GitHub (prerelease) |
---|---|---|
Deveel.Webhooks.Receiver.Twilio | ||
Deveel.Webhooks.Receiver.SendGrid | ||
Deveel.Webhooks.Receiver.Facebook |
You can obtain the stable versions of these libraries from the NuGet Official channel.
To get the latest pre-release versions of the packages you can restore from the Deveel Package Manager.
We would like to help you get started with this framework and to eventually extend it: please refer to the Documentation section, or to the Official Website that we have produced for you.
The easiest way to get started is to follow the Getting Started guide, but you can also refer to the Frequently Asked Questions section to get answers to the most common questions.
While working on a .NET Core 3.1/.NET 5 PaaS (Platform-as-a-Service) project that functionally required the capability of users of the service being able to create system-to-system subscriptions and notifications of events through HTTP channel (that is typically named webhooks, or HTTP callbacks), I started my design with the ambition to use existing solutions, to avoid the bad practice of reinventing the wheel, but I ended up frustrated in such ambition:
- Microsoft's ASP.NET Webhooks project was archived and moved back to the Microsoft ASP Labs (that has no visibility on its release), aiming one day to provide compatibility with .NET Core (which eventually evolved, becoming LTS)
- Both Microsoft's projects (the legacy and the experimental ones) are not compatible with the latest .NET stacks (.NET 5 / .NET 6)
- Microsoft's experimental projects never implemented any capability of handling subscriptions, and eventually removed the sender capability, focusing exclusively on receivers
- Alternative implementations providing similar capabilities are embedded and organic parts of larger frameworks (like ASP.NET Boilerplate), that would have forced me to adopt the the entirety of such frameworks, beyond my design intentions
The documentation of the framework will provide you with more details on the requirements, configurations, usage and extensibility of the framework.
Anyway, to help you get started with the framework, please consider the following examples that show how to create a simple webhook management service, that handle subscriptions and notifications, and a client receiver.
As a provider of service, this library provides functions to handle the two main aspects of the webhook pattern:
- Subscriptions: the capability of a client to subscribe to a specific event, providing an endpoint to be notified
- Notifications: the capability of a server to send notifications to the subscribed endpoints
The following example shows how to create a webhook subscription, and how to send a notification to the subscriber endpoints:
using Microsoft.AspNetCore.Builder;
using Deveel.Webhooks;
namespace Example {
public class Program {
public static void Main(string[] args) {
var builder = WebApplication.CreateBuilder(args);
// ...
builder.Services.AddWebhookSubscriptions<MongoWebhookSubscription>(subs => {
subs.UseMongoDb("mongodb://localhost:27017")
.UseSubscriptionResolver();
});
builder.Services.AddWebhookNotifier<MyWebhook>(notifier => {
notifier.UseSender(sender => {
sender.Configure(options => {
options.Timeout = TimeSpan.FromSeconds(30);
});
});
});
var app = builder.Build();
// ...
// ... and notify the receivers manually ...
app.MapPost("/webhooks", async (HttpContext context,
[FromServices] IWebhookSender<MyWebhook> sender, [FromBody] MyWebhookModel webhook) => {
var destination = webhook.Destination.ToWebhookDestination();
var result = await sender.SendAsync(destination, webhook, context.HttpContext.RequestAborted);
// ...
return Results.Ok();
});
// ... or notify the webhooks automatically from subscriptions
app.MapPost("/webhooks/notify", async (HttpContext context,
[FromServices] IWebhookNotifier<MyWebhook> notifier, [FromBody] MyEventModel eventModel) => {
var eventInfo = eventModel.AsEventInfo();
var result = await notifier.NotifyAsync(eventInfo, context.HttpContext.RequestAborted);
// you can log the result of the notification to all receivers ...
return Results.Ok();
});
app.Run();
}
}
}
The framework also provides a set of built-in receivers that can be used to handle the incoming notifications from the subscribed endpoints in your application.
The following example shows how to create a receiver for a webhook that is backed by a Facebook Messenger message:
namespace Example {
public class Program {
public static void Main(string[] args) {
var builder = WebApplication.CreateBuilder(args);
// ...
builder.Services.AddFacebookReceiver()
.AddHandler<MyFacebookWebhookHandler>();
var app = builder.Build();
// ...
// ... you can handle all the incoming webhooks at "/webhooks/facebook"
// invoking all the handlers registered in the service collection ...
app.MapFacebookWebhook("/webhooks/facebook");
// ... or you can handle the incoming webhooks manually ...
app.MapFacebookWebhook("/webhooks/facebook2", async (FacebookWebhook webhook, IService service, CancellationToken ct) => {
// ...
await service.DoSomethingAsync(webhook, ct);
});
app.Run();
}
}
}
Contributions to open-source projects, like Deveel Webhooks, is generally driven by interest in using the product and services, if they would respect some of the expectations we have for its functions.
The best ways to contribute and improve the quality of this project are by trying it, filing issues, joining in design conversations, and making pull-requests.
Please refer to the Contributing Guidelines to receive more details on how you can contribute to this project.
We aim to address most of the questions you might have by providing documentations, answering frequently asked questions and following up on issues like bug reports and feature requests.
This project is released under the Apache 2 Open-Source Licensing agreement.