In this article, I will show you the basics of the Webhook mechanism that uses a publish-subscribe pattern in the ASP.NET CORE 3.1 project.
What is Webhook
Webhooks are user-defined HTTP callbacks. They are usually triggered by some events, such as pushing code to a repository or a comment being posted to a blog. When that event occurs, the source site makes an HTTP request to the URL configured for the Webhook. Users can configure them to cause events on one site to invoke behavior on another.
(https://en.wikipedia.org/wiki/Webhook)
We have implemented a Webhook mechanism that uses a publish-subscribe pattern to our ASP.NET Boilerplate and ASP.NET ZERO projects. Users can subscribe to a Webhook event(s) (for example User.Created
, Notification.NewNotification
etc…) then when that event occurs application publishes a Webhook(s) to subscribed endpoints.
Implementation
Note: In this article, I will not show any basic CRUD operation code. I will just share the parts that I think are important. If you want all codes and more you can check* ASP.NET Boilerplate github page.
WebhookSubscription: An entity that we will store Webhook subscriptions.
The important thing is the subscription’s secret. You should set it when you create a Webhook subscription and never change it. (Unless your custom logic contains something like change Webhook secret)
We will sign our Webhook payload using that secret right before sending it to the client. Then when the client receives the Webhook, it will check if the Webhook payload has been signed correctly. The client will be able to verify that the data comes from the correct source. So, the secret is important.
You can manage it with basic CRUD operations (example: WebhookSubscriptionManager)
WebhookEvent: An entity that we will store Webhook information. Webhook events can be sent to a large number of subscriptions. Since we send Webhook in separate background job, we need to store Webhook data to use it again and again.
You can manage it with basic CRUD operations (example: WebhookEventStore)
WebhookSendAttempt: An entity that we will store all information about Webhook send process.
You can manage it with basic CRUD operations (example: WebhookSendAttemptStore)
WebhookDefinition: Definitions of Webhook that system has.
You can manage it with basic CRUD operations (example: WebhookDefinitionManager)
WebhookPayload: Webhook payload pattern that we use to send our Webhooks.
WebhookPublisher
The class that we will use to publish Webhooks to all subscriptions. It is responsible to check subscription and create a background job which sends Webhooks.
Publishing workflow:
Code:
(You can check github.com/aspnetboilerplate/DefaultWebhookPublisher for more information)
WebhookSenderJob
Workflow:
Code:
(You can check github.com/aspnetboilerplate/DefaultWebhookPublisher for more information)
Workflow:
Code:
SendWebhook:
GetSerializedBodyAsync:
SignWebhookRequest:
SendHttpRequest:
*Note:* If you use ASP.Net Core, using *IHttpClientFactory* is recommend way to create HttpClient. For example you can check github.com/aspnetboilerplate/AspNetCoreWebhookSender
(You can check the rest of the code and see all together in: github.com/aspnetboilerplate/DefaultWebhookSender.)
All done! Now we can use Webhook publisher.
Testing Our Code
On Server-side
Add a subscription:
Send Webhook:
Publishing is done. It will be sent to all subscribed clients.
*C# client-side example:*
For more information you can check;
https://aspnetboilerplate.com/Pages/Documents/Webhook-System
https://github.com/aspnetboilerplate/aspnetboilerplate