Skip to content

Commit a8b0579

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

File tree

4 files changed

+98
-93
lines changed

4 files changed

+98
-93
lines changed

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

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -141,46 +141,49 @@ builder.WebhookEvents().Clear().AddCms(false);
141141
You can modify existing webhook events, such as changing the payload format, by creating a custom implementation:
142142

143143
```csharp
144+
using Microsoft.Extensions.Options;
145+
using Umbraco.Cms.Core;
146+
using Umbraco.Cms.Core.Configuration.Models;
147+
using Umbraco.Cms.Core.DeliveryApi;
148+
using Umbraco.Cms.Core.Models;
149+
using Umbraco.Cms.Core.Notifications;
150+
using Umbraco.Cms.Core.PublishedCache;
151+
using Umbraco.Cms.Core.Services;
152+
using Umbraco.Cms.Core.Sync;
153+
using Umbraco.Cms.Core.Webhooks;
154+
155+
namespace CommunityDocs.Controllers;
156+
144157
[WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)]
145-
public class MyCustomContentPublishedWebhookEvent : WebhookEventContentBase<ContentPublishedNotification, IContent>
158+
public class MyCustomContentPublishedWebhookEvent(
159+
IWebhookFiringService webhookFiringService,
160+
IWebhookService webhookService,
161+
IOptionsMonitor<WebhookSettings> webhookSettings,
162+
IServerRoleAccessor serverRoleAccessor,
163+
IApiContentBuilder apiContentBuilder,
164+
IPublishedContentCache publishedContentCache):
165+
WebhookEventContentBase<ContentPublishedNotification, IContent>(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor)
146166
{
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-
163167
public override string Alias => "Umbraco.ContentPublish";
164168
protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities;
165169

166170
protected override object? ConvertEntityToRequestPayload(IContent entity)
167171
{
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);
172+
var cachedPublishedContent = publishedContentCache.GetById(entity.Key);
174173

175174
return new
176175
{
177176
CustomData = "Your data",
178-
PublishedContent = publishedContent is null ? null : _apiContentBuilder.Build(publishedContent)
177+
PublishedContent = cachedPublishedContent is null ? null : apiContentBuilder.Build(cachedPublishedContent)
179178
};
180179
}
181180
}
182181
```
183182

183+
{% hint style="info" %}
184+
Umbraco developers will need to inject `IPublishedContentCache`, `IPublishedMediaCache`, `IPublishedMemberCache` and `IPublishedContentTypeCache` dependencies individually, instead of injecting the `IPublishedSnapshotAccessor` as would have been done previously.
185+
{% endhint %}
186+
184187
To replace the default Umbraco webhook with your custom implementation:
185188

186189
```csharp
@@ -196,20 +199,24 @@ public class MyComposer : IComposer
196199
## Webhook Settings
197200

198201
Webhook settings are configured in `appsettings.*.json` under `Umbraco::CMS`:
199-
202+
{% code title="appsettings.json" %}
200203
```json
201-
"Umbraco": {
202-
"CMS": {
203-
"Webhook": {
204-
"Enabled": true,
205-
"MaximumRetries": 5,
206-
"Period": "00:00:10",
207-
"EnableLoggingCleanup": true,
208-
"KeepLogsForDays": 30
204+
{
205+
"$schema": "appsettings-schema.json",
206+
"Umbraco": {
207+
"CMS": {
208+
"Webhook": {
209+
"Enabled": true,
210+
"MaximumRetries": 5,
211+
"Period": "00:00:10",
212+
"EnableLoggingCleanup": true,
213+
"KeepLogsForDays": 30
214+
}
215+
}
209216
}
210-
}
211217
}
212218
```
219+
{% endcode %}
213220

214221
| Setting | Description |
215222
|---------|-------------|

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,14 @@ protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPubl
140140

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

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

153153
3. **ProcessWebhooks Implementation**:

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

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ description: Umbraco webhooks enable seamless integration and real-time updates
77
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.
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,37 +31,31 @@ 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-
3934
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.
4035

4136
### Custom Headers
42-
4337
You 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
54-
5547
Each webhook event sends a JSON payload. The following types of payloads are available by default.
5648

5749
#### Legacy
58-
5950
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`).
60-
#### Minimal
6151

52+
#### Minimal
6253
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.
63-
#### Extended
6454

55+
#### Extended
6556
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.
6657

6758
### Configuring Payload Types
68-
6959
Payload type can be configured in the following ways:
7060

7161
- 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.
@@ -168,46 +158,49 @@ builder.WebhookEvents().Clear().AddCms(false);
168158
You can modify existing webhook events, such as changing the payload format, by creating a custom implementation:
169159

170160
```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+
171174
[WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)]
172-
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)
173183
{
174-
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
175-
private readonly IApiContentBuilder _apiContentBuilder;
176-
177-
public MyCustomContentPublishedWebhookEvent(
178-
IWebhookFiringService webhookFiringService,
179-
IWebhookService webhookService,
180-
IOptionsMonitor<WebhookSettings> webhookSettings,
181-
IServerRoleAccessor serverRoleAccessor,
182-
IPublishedSnapshotAccessor publishedSnapshotAccessor,
183-
IApiContentBuilder apiContentBuilder)
184-
: base(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor)
185-
{
186-
_publishedSnapshotAccessor = publishedSnapshotAccessor;
187-
_apiContentBuilder = apiContentBuilder;
188-
}
189-
190184
public override string Alias => "Umbraco.ContentPublish";
191185
protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities;
192186

193187
protected override object? ConvertEntityToRequestPayload(IContent entity)
194188
{
195-
if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
196-
{
197-
return null;
198-
}
199-
200-
IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(entity.Key);
189+
var cachedPublishedContent = publishedContentCache.GetById(entity.Key);
201190

202191
return new
203192
{
204193
CustomData = "Your data",
205-
PublishedContent = publishedContent is null ? null : _apiContentBuilder.Build(publishedContent)
194+
PublishedContent = cachedPublishedContent is null ? null : apiContentBuilder.Build(cachedPublishedContent)
206195
};
207196
}
208197
}
209198
```
210199

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+
211204
To replace the default Umbraco webhook with your custom implementation:
212205

213206
```csharp
@@ -224,19 +217,24 @@ public class MyComposer : IComposer
224217

225218
Webhook settings are configured in `appsettings.*.json` under `Umbraco::CMS`:
226219

220+
{% code title="appsettings.json" %}
227221
```json
228-
"Umbraco": {
229-
"CMS": {
230-
"Webhook": {
231-
"Enabled": true,
232-
"MaximumRetries": 5,
233-
"Period": "00:00:10",
234-
"EnableLoggingCleanup": true,
235-
"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+
}
236234
}
237-
}
238235
}
239236
```
237+
{% endcode %}
240238

241239
| Setting | Description |
242240
|---------|-------------|

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,14 @@ protected override IEnumerable<IContent> GetEntitiesFromNotification(ContentPubl
142142

143143
protected override object? ConvertEntityToRequestPayload(IContent entity)
144144
{
145-
if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
146-
{
147-
return null;
148-
}
145+
var cachedPublishedContent = publishedContentCache.GetById(entity.Key);
149146

150-
IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(entity.Key);
151-
return publishedContent is null ? null : _apiContentBuilder.Build(publishedContent);
152-
}
147+
return new
148+
{
149+
CustomData = "Your data",
150+
PublishedContent = cachedPublishedContent is null ? null : apiContentBuilder.Build(cachedPublishedContent)
151+
};
152+
}
153153
```
154154

155155
3. **ProcessWebhooks Implementation**:

0 commit comments

Comments
 (0)