Skip to content

Commit b324ba0

Browse files
committed
Update webhooks code samples to replace IPublishedSnapshotAccessor with IPublishedContentCache, IPublishedMediaCache, IPublishedMemberCache and IPublishedContentTypeCache dependencies.
1 parent f629495 commit b324ba0

File tree

5 files changed

+183
-167
lines changed

5 files changed

+183
-167
lines changed

15/umbraco-cms/reference/webhooks/README.md

Lines changed: 88 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ description: Umbraco webhooks enable seamless integration and real-time updates
44

55
# Webhooks
66

7-
Webhooks provide real-time, event-driven communication within Umbraco. They enable external services to react to content changes instantly by sending HTTP requests when specific events occur. This allows you to integrate with third-party services, automate workflows, and synchronize data effortlessly.
7+
Webhooks provide real-time, event-driven communication within Umbraco. They enable external services to react to content changes instantly by sending HTTP requests when specific events occur. This allows developers to integrate with third-party services, automate workflows, and synchronize data effortlessly.
88

99
## Getting Started
10-
1110
To manage webhooks, navigate to **Settings > Webhooks** in the Umbraco backoffice.
1211

1312
![Webhooks section](images/webhook-section-v14.png)
@@ -17,13 +16,10 @@ To create a webhook, click **Create**. This opens the webhook creation screen wh
1716
![Creating a webhook](images/create-webhook-v14.png)
1817

1918
## Configuring a Webhook
20-
2119
### URL
22-
2320
The `Url` is the endpoint where the webhook will send an HTTP request when the selected event is triggered. Ensure this endpoint is publicly accessible and capable of handling incoming requests.
2421

2522
### Events
26-
2723
Webhooks are triggered by specific events in Umbraco. By default, the following events are available:
2824

2925
| Event Name | Description |
@@ -35,48 +31,69 @@ Webhooks are triggered by specific events in Umbraco. By default, the following
3531
| Media Saved | Fires when a media item is saved. |
3632

3733
### Content Type Filtering
38-
39-
For **Content** or **Media** events, you can specify whether the webhook should trigger for all content types or only specific ones. This is useful when you only need webhooks for certain document types, such as blog posts or products.
34+
For **Content** or **Media** events, developers can specify whether the webhook should trigger for all content types or only specific ones. This is useful when activating webhooks for certain document types, such as blog posts or products.
4035

4136
### Custom Headers
42-
43-
You can define custom HTTP headers that will be included in the webhook request. Common use cases include:
37+
Developers can define custom HTTP headers that will be included in the webhook request. Common use cases include:
4438

4539
- Specifying request format: `Accept: application/json`
4640
- Adding authentication tokens: `Authorization: Bearer <your-token>`
4741
- Including security headers
4842

4943
## Default Behavior of Umbraco Webhooks
50-
5144
Umbraco webhooks come with predefined settings and behaviors.
5245

5346
### JSON Payload
47+
Each webhook event sends a JSON payload. The following types of payloads are available by default.
5448

55-
Each webhook event sends a JSON payload. For example, the `Content Published` event includes full content details:
49+
#### Legacy
50+
This is the current default but will be removed in a future version. Legacy payloads follow the format used before version 16. They are inconsistent and may include data that should not be exposed or has been superseded (e.g., use of `int` instead of `Guid`).
5651

57-
```json
52+
#### Minimal
53+
This will become the default in version 17 and later. Minimal payloads include only essential information to identify the resource. For most events, this means a unique identifier. Some events may include additional data. For example, a document publish event also includes the list of published cultures.
54+
55+
#### Extended
56+
Extended payloads include all relevant information for an event, where available. However, sensitive data, such as usernames, member names, or email addresses, is excluded for privacy and security reasons. If an extended payload is not available for an event, the system falls back to the minimal payload.
57+
58+
### Configuring Payload Types
59+
Payload type can be configured in the following ways:
60+
61+
- Changing the appsetting `Umbraco:CMS:Webhook:PayloadType`. Be aware that the system that uses this value runs before any composers. If you manipulate the `WebhookEventCollectionBuilder` in any way, then those methods will not automatically pick up this app setting.
62+
- Passing in the PayloadType into the `WebhookEventCollectionBuilderExtensions` methods to control which webhook events are added.
63+
64+
```csharp
65+
using Umbraco.Cms.Core.Composing;
66+
using Umbraco.Cms.Core.Webhooks;
67+
68+
namespace Umbraco.Cms.Web.UI.Composers;
69+
70+
// this composer clears all registered webhooks and then adds all (umbraco provided) webhooks with their extended payloads
71+
public class AllWebhookComposer : IComposer
5872
{
59-
"name": "Root",
60-
"createDate": "2023-12-11T12:02:38.9979314",
61-
"updateDate": "2023-12-11T12:02:38.9979314",
62-
"route": {
63-
"path": "/",
64-
"startItem": {
65-
"id": "c1922956-7855-4fa0-8f2c-7af149a92135",
66-
"path": "root"
73+
public void Compose(IUmbracoBuilder builder)
74+
{
75+
builder.WebhookEvents().Clear().AddCms(onlyDefault: false, payloadType: WebhookPayloadType.Extended);
6776
}
68-
},
69-
"id": "c1922956-7855-4fa0-8f2c-7af149a92135",
70-
"contentType": "root",
71-
"properties": {}
7277
}
78+
7379
```
7480

75-
The `Content Deleted` event sends only the content ID:
81+
- Manually manipulating the `WebhookEventCollectionBuilder`.
7682

77-
```json
83+
```csharp
84+
using Umbraco.Cms.Core.Composing;
85+
using Umbraco.Cms.Core.Webhooks.Events;
86+
87+
namespace Umbraco.Cms.Web.UI.Composers;
88+
89+
// since legacy is the default, this composer removes the old content published webhookevent and changes it with the new extended version.
90+
public class AllWebhookComposer : IComposer
7891
{
79-
"id": "c1922956-7855-4fa0-8f2c-7af149a92135"
92+
public void Compose(IUmbracoBuilder builder)
93+
{
94+
builder.WebhookEvents().Remove<LegacyContentPublishedWebhookEvent>();
95+
builder.WebhookEvents().Add<ExtendedContentPublishedWebhookEvent>();
96+
}
8097
}
8198
```
8299

@@ -138,50 +155,53 @@ builder.WebhookEvents().Clear().AddCms(false);
138155

139156
### Replacing Webhook Events
140157

141-
You can modify existing webhook events, such as changing the payload format, by creating a custom implementation:
158+
Developers can modify existing webhook events, such as changing the payload format, by creating a custom implementation:
142159

143160
```csharp
161+
using Microsoft.Extensions.Options;
162+
using Umbraco.Cms.Core;
163+
using Umbraco.Cms.Core.Configuration.Models;
164+
using Umbraco.Cms.Core.DeliveryApi;
165+
using Umbraco.Cms.Core.Models;
166+
using Umbraco.Cms.Core.Notifications;
167+
using Umbraco.Cms.Core.PublishedCache;
168+
using Umbraco.Cms.Core.Services;
169+
using Umbraco.Cms.Core.Sync;
170+
using Umbraco.Cms.Core.Webhooks;
171+
172+
namespace CommunityDocs.Controllers;
173+
144174
[WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)]
145-
public class MyCustomContentPublishedWebhookEvent : WebhookEventContentBase<ContentPublishedNotification, IContent>
175+
public class MyCustomContentPublishedWebhookEvent(
176+
IWebhookFiringService webhookFiringService,
177+
IWebhookService webhookService,
178+
IOptionsMonitor<WebhookSettings> webhookSettings,
179+
IServerRoleAccessor serverRoleAccessor,
180+
IApiContentBuilder apiContentBuilder,
181+
IPublishedContentCache publishedContentCache):
182+
WebhookEventContentBase<ContentPublishedNotification, IContent>(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor)
146183
{
147-
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
148-
private readonly IApiContentBuilder _apiContentBuilder;
149-
150-
public MyCustomContentPublishedWebhookEvent(
151-
IWebhookFiringService webhookFiringService,
152-
IWebhookService webhookService,
153-
IOptionsMonitor<WebhookSettings> webhookSettings,
154-
IServerRoleAccessor serverRoleAccessor,
155-
IPublishedSnapshotAccessor publishedSnapshotAccessor,
156-
IApiContentBuilder apiContentBuilder)
157-
: base(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor)
158-
{
159-
_publishedSnapshotAccessor = publishedSnapshotAccessor;
160-
_apiContentBuilder = apiContentBuilder;
161-
}
162-
163184
public override string Alias => "Umbraco.ContentPublish";
164185
protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities;
165186

166187
protected override object? ConvertEntityToRequestPayload(IContent entity)
167188
{
168-
if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
169-
{
170-
return null;
171-
}
172-
173-
IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(entity.Key);
189+
var cachedPublishedContent = publishedContentCache.GetById(entity.Key);
174190

175191
return new
176192
{
177193
CustomData = "Your data",
178-
PublishedContent = publishedContent is null ? null : _apiContentBuilder.Build(publishedContent)
194+
PublishedContent = cachedPublishedContent is null ? null : apiContentBuilder.Build(cachedPublishedContent)
179195
};
180196
}
181197
}
182198
```
183199

184-
To replace the default Umbraco webhook with your custom implementation:
200+
{% hint style="info" %}
201+
Umbraco developers will need to inject `IPublishedContentCache`, `IPublishedMediaCache`, `IPublishedMemberCache` and `IPublishedContentTypeCache` dependencies individually, instead of injecting the `IPublishedSnapshotAccessor` as would have been done previously.
202+
{% endhint %}
203+
204+
The code below shows an example that replaces the default Umbraco webhook with a custom implementation:
185205

186206
```csharp
187207
public class MyComposer : IComposer
@@ -197,19 +217,24 @@ public class MyComposer : IComposer
197217

198218
Webhook settings are configured in `appsettings.*.json` under `Umbraco::CMS`:
199219

220+
{% code title="appsettings.json" %}
200221
```json
201-
"Umbraco": {
202-
"CMS": {
203-
"Webhook": {
204-
"Enabled": true,
205-
"MaximumRetries": 5,
206-
"Period": "00:00:10",
207-
"EnableLoggingCleanup": true,
208-
"KeepLogsForDays": 30
222+
{
223+
"$schema": "appsettings-schema.json",
224+
"Umbraco": {
225+
"CMS": {
226+
"Webhook": {
227+
"Enabled": true,
228+
"MaximumRetries": 5,
229+
"Period": "00:00:10",
230+
"EnableLoggingCleanup": true,
231+
"KeepLogsForDays": 30
232+
}
233+
}
209234
}
210-
}
211235
}
212236
```
237+
{% endcode %}
213238

214239
| Setting | Description |
215240
|---------|-------------|
@@ -221,4 +246,4 @@ Webhook settings are configured in `appsettings.*.json` under `Umbraco::CMS`:
221246

222247
## Testing Webhooks
223248

224-
Use [Beeceptor](https://beeceptor.com/) or [RequestBin](https://pipedream.com/requestbin) to test your event trigger integrations before deploying them to production.
249+
Use [Beeceptor](https://beeceptor.com/) or [RequestBin](https://pipedream.com/requestbin) to test the event trigger integrations before deploying them to production.

15/umbraco-cms/reference/webhooks/expanding-webhook-events.md

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
---
22
description: >-
3-
Explore new webhook event options, detailed setup, specific content triggers,
4-
and improved logging and retry mechanisms
3+
Explore new webhook event options, detailed setup, specific content triggers, and improved logging and retry mechanisms.
54
---
65

76
# Expanding Webhook Events
87

98
## Introduction
109

11-
With Umbraco, you can create your own webhook events.
10+
Umbraco developers can create their own webhook events.
1211

13-
This documentation guides you through the process of implementing your webhook events using the `WebhookEventBase<TNotification>` base class.
12+
This article demonstrates the process of implementing custom webhook events using the `WebhookEventBase<TNotification>` base class.
1413

1514
## Creating an Event with the WebhookEventBase
1615

1716
The `WebhookEventBase<TNotification>` class serves as the foundation for creating custom webhook events. Here's a brief overview of its key components:
1817

19-
* **Alias**: The property that must be overridden to provide a unique identifier for your webhook event.
18+
* **Alias**: The property that must be overridden to provide a unique identifier for the webhook event.
2019
* **EventName**: A property that represents the name of the event. It is automatically set based on the provided alias unless explicitly specified.
2120
* **EventType**: A property that categorizes the event type. It defaults to "Others" but can be customized using the `WebhookEventAttribute`.
2221
* **WebhookSettings**: The property containing the current webhook settings.
@@ -38,14 +37,14 @@ To create a custom webhook event, follow these steps:
3837
```
3938
2. **Override the Alias Property**:
4039

41-
Provide a unique identifier for your event using the `Alias` property:
40+
Provide a unique identifier for the event using the `Alias` property:
4241

4342
```csharp
4443
public override string Alias => "YourUniqueAlias";
4544
```
4645
3. **Apply `WebhookEventAttribute` (Optional)**:
4746

48-
You can use the `WebhookEventAttribute` to specify the event name and type. Apply this attribute to your custom event class:
47+
Use the `WebhookEventAttribute` to specify the event name and type. Apply this attribute to the custom event class:
4948

5049
```csharp
5150
[WebhookEvent("Your Event Name", "YourEventType")]
@@ -55,13 +54,14 @@ To create a custom webhook event, follow these steps:
5554
}
5655
```
5756

58-
Umbraco already has some types as constants, which you can find at `Constants.WebhookEvents.Types`. If you do not specify this attribute, the event name will default to your alias, and the type will default to `Other`.
57+
Umbraco already has some types as constants, which you can find at `Constants.WebhookEvents.Types`. If this attribute is not specified, the event name will default to the alias, and the type will default to `Other`.
58+
4.
5959
4. **Implement Notification Handling**:
6060

6161
If needed, customize the handling of the notification in the `HandleAsync` method.
6262
5. **Register Your Webhook Event**:
6363

64-
Ensure that Umbraco is aware of your custom event by registering it in a composer:
64+
Ensure that Umbraco is aware of the custom event by registering it in a composer:
6565

6666
```csharp
6767
using Umbraco.Cms.Core.Composing;
@@ -74,11 +74,11 @@ To create a custom webhook event, follow these steps:
7474
}
7575
}
7676
```
77-
6. **Implement Optional Overrides**: Depending on your requirements, you can override methods such as `ConvertNotificationToRequestPayload` and `ShouldFireWebhookForNotification` to customize the behavior of your webhook event.
77+
6. **Implement Optional Overrides**: Depending on requirements, methods such as `ConvertNotificationToRequestPayload` and `ShouldFireWebhookForNotification` can be overridden to customize the behavior of the webhook event.
7878

7979
### Sample Implementation
8080

81-
Here's a basic example of a custom webhook event:
81+
The code below shows a sample implementation of a custom webhook event. The `YourCustomEvent` class is derived from the `WebhookEventBase<YourNotificationType>` class, and it overrides the `Alias` property to provide a unique identifier for the event. The `WebhookEventAttribute` is applied to the class to specify the event name and type.
8282

8383
```csharp
8484
[WebhookEvent("Your Custom Event", "CustomEventType")]
@@ -111,7 +111,7 @@ public class YourCustomEvent : WebhookEventBase<YourNotificationType>
111111

112112
## Creating an Event with the WebhookEventContentBase\<TNotification, TEntity>
113113

114-
For scenarios where your webhook event is content-specific, Umbraco provides another base class: `WebhookEventContentBase<TNotification, TEntity>`. This class is an extension of the generic `WebhookEventBase<TNotification>` and introduces content-related functionalities.
114+
For scenarios where the webhook event is content-specific, Umbraco provides another base class: `WebhookEventContentBase<TNotification, TEntity>`. This class is an extension of the generic `WebhookEventBase<TNotification>` and introduces content-related functionalities.
115115

116116
The `WebhookEventContentBase<TNotification, TEntity>` class is designed for content-specific webhook events, where `TEntity` is expected to be a type that implements the `IContentBase` interface.
117117

@@ -131,23 +131,21 @@ To leverage the `WebhookEventContentBase<TNotification, TEntity>` class, follow
131131
* **GetEntitiesFromNotification**: Implement this method to extract content entities from the notification.
132132
* **ConvertEntityToRequestPayload**: Implement this method to customize the content entity payload before sending it to webhooks.
133133

134-
If we take a look at the `ContentPublishedWebhookEvent`, we can see how these methods are overridden.
135-
136-
{% include "../../.gitbook/includes/obsolete-warning-ipublishedsnapshotaccessor.md" %}
134+
The `ContentPublishedWebhookEvent` class demonstrates how these methods are overridden.
137135

138136
```csharp
139137
protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities;
140138

141139
protected override object? ConvertEntityToRequestPayload(IContent entity)
142140
{
143-
if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
144-
{
145-
return null;
146-
}
141+
var cachedPublishedContent = publishedContentCache.GetById(entity.Key);
147142

148-
IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(entity.Key);
149-
return publishedContent is null ? null : _apiContentBuilder.Build(publishedContent);
150-
}
143+
return new
144+
{
145+
CustomData = "Your data",
146+
PublishedContent = cachedPublishedContent is null ? null : apiContentBuilder.Build(cachedPublishedContent)
147+
};
148+
}
151149
```
152150

153151
3. **ProcessWebhooks Implementation**:

0 commit comments

Comments
 (0)