versionFrom | versionTo |
---|---|
9.0.0 |
10.0.0 |
:::note If you are using Umbraco 8 or any lower version, please refer to the ContentService Events article instead. :::
The ContentService class is the most commonly used type when extending Umbraco using notifications. ContentService implements IContentService. It provides access to operations involving IContent.
Example usage of the ContentPublishingNotification:
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
namespace MySite
{
public class DontShout : INotificationHandler<ContentPublishingNotification>
{
public void Handle(ContentPublishingNotification notification)
{
foreach (var node in notification.PublishedEntities)
{
if (node.ContentType.Alias.Equals("announcement"))
{
var newsArticleTitle = node.GetValue<string>("title");
if (newsArticleTitle.Equals(newsArticleTitle.ToUpper()))
{
notification.CancelOperation(new EventMessage("Corporate style guideline infringement",
"Don't put the announcement title in upper case, no need to shout!",
EventMessageType.Error));
}
}
}
}
}
}
Notification | Members | Description |
---|---|---|
ContentSavingNotification |
|
Published when the IContentService.Save is called in the API. NOTE: It can be skipped completely if the parameter "raiseEvents" is set to false during the Save method call (true by default). SavedEntities: The collection of IContent objects being saved. NOTE: If the entity is brand new then HasIdentity will equal false. |
ContentSavedNotification |
|
Published when IContentService.Save is called in the API and after data has been persisted. NOTE: It can be skipped completely if the parameter "raiseEvents" is set to false during the Save method call (true by default). NOTE: See here on how to determine if the entity is brand new SavedEntities: The saved collection of IContent objects. |
ContentPublishingNotification |
|
Published when IContentService.Publishing is called in the API. NOTE: It can be skipped completely if the parameter "raiseEvents" is set to false during the Publish method call (true by default). NOTE: If the entity is brand new then HasIdentity will equal false. PublishedEntities: The collection of IContent objects being published. |
ContentPublishedNotification |
|
Published when IContentService.Publish is called in the API and after data has been published. NOTE: It can be skipped completely if the parameter "raiseEvents" is set to false during the Publish method call (true by default). NOTE: See here on how to determine if the entity is brand new PublishedEntities: The published collection of IContent objects. |
ContentUnpublishingNotification |
|
Published when IContentService.UnPublishing is called in the API. UnpublishedEntities: The collection of IContent being unpublished. |
ContentUnpublishedNotification |
|
Published when IContentService.UnPublish is called in the API and after data has been unpublished. UnpublishedEntities: The collection of unpublished IContent. |
ContentCopyingNotification |
|
Published when IContentService.Copy is called in the API. The notification is published after a copy object has been created and had its parentId updated and its state has been set to unpublished.
|
ContentCopiedNotification |
|
Published when IContentService.Copy is called in the API. The notification is published after the content object has been copied.
|
ContentMovingNotification |
|
Published when IContentService.Move is called in the API. NOTE: If the target parent is the Recycle bin, this notification is never published. Try the ContentMovingToRecycleBinNotification instead. MoveInfoCollection will for each moving entity provide:
|
ContentMovedNotification |
|
Published when IContentService.Move is called in the API.
The notification is published after the content object has been moved. NOTE: If the target parent is the Recycle bin, this notification is never published. Try the ContentMovedToRecycleBinNotification instead. MoveInfoCollection will for each moving entity provide:
|
ContentMovingToRecycleBinNotification |
|
Published when ContentService.MoveToRecycleBin is called in the API. MoveInfoCollection will for each moving entity provide:
|
ContentMovedToRecycleBinNotification |
|
Published when ContentService.MoveToRecycleBin is called in the API. Is published after the content has been moved to the RecycleBin MoveInfoCollection will for each moving entity provide:
|
ContentDeletingNotification |
|
Published when ContentService.DeleteContentOfType, ContentService.Delete, ContentService.EmptyRecycleBin are called in the API. DeletedEntities: Gets the collection of IContent objects being deleted. |
ContentDeletedNotification |
|
Published when ContentService.Delete, ContentService.EmptyRecycleBin are called in the API, and the entity has been deleted. DeletedEntities: Gets the collection of deleted IContent objects. |
ContentDeletingVersionsNotification |
|
Published when ContentService.DeleteVersion, ContentService.DeleteVersions are called in the API.
|
ContentDeletedVersionsNotification |
|
Published when ContentService.DeleteVersion, ContentService.DeleteVersions are called in the API, and the version has been deleted.
|
ContentRollingBackNotification |
|
Published when ContentService.Rollback is called in the API. Entity: Gets the IContent object being rolled back. |
ContentRolledBackNotification |
|
Published when ContentService.Rollback is called in the API, after the content has been rolled back. Entity: Gets the IContent object being rolled back. |
ContentSendingToPublishNotification |
|
Published when ContentService.SendToPublication is called in the API. Entity: Gets the IContent object being sent to publish. |
ContentSentToPublishNotification |
|
Published when ContentService.SendToPublication is called in the API, after the entity has been sent to publication. Entity: Gets the IContent object being sent to publish. |
ContentEmptyingRecycleBinNotification |
|
Published when ContentService.EmptyRecycleBin is called in the API. DeletedEntities: The collection of IContent objects being deleted. |
ContentEmptiedRecycleBinNotification |
|
Published when ContentService.EmptyRecycleBin is called in the API, after the RecycleBin has been emptied. DeletedEntities: The collection of deleted IContent object. |
ContentSavedBlueprintNotification |
|
Published when ContentService.SavedBlueprint is called in the API. SavedBlueprint: Gets the saved blueprint IContent object |
ContentDeletedBlueprintNotification |
|
Published when ContentService.DeletedBlueprint is called in the API. DeletedBlueprints: The collection of deleted blueprint IContent |
Umbraco V8 introduced the concept of Variants for Document Types, initially to allow different language variants of particular properties within a Document Type to be edited/translated based on the languages configured in your instance of Umbraco.
These variants can be saved, published, and unpublished independently of each other. (Unpublishing a 'mandatory language' variant of a content item - will trigger all culture variants to be unpublished).
This poses a problem when handling notifications from the ContentService - eg which culture got published? Do I want to run my 'custom' code that fires on save if it's only the Spanish version that's been published? Also, if only the Spanish variant is 'unpublished' - that feels like a different situation than if 'all the variants' have been 'unpublished'. Depending on which event you are handling there are helper methods you can call to find out.
When handling the ContentSavingNotification which will be published whenever a variant is saved. You can tell 'which' variant has triggered the save using an extension method on the ContentSavingNotification called 'IsSavingCulture'
public bool IsSavingCulture(IContent content, string culture);
As an example, you could check which cultures are being saved (it could be multiple if multiple checkboxes are checked)
public void Handle(ContentSavingNotification notification)
{
foreach (var entity in notification.SavedEntities)
{
// Cultures being saved
var savingCultures = entity.AvailableCultures
.Where(culture => notification.IsSavingCulture(entity, culture)).ToList();
// or
if (notification.IsSavingCulture(entity, "en-GB"))
{
// Do things differently if the UK version of the page is being saved.
}
}
}
With the Saved notification you can similarly use the 'HasSavedCulture' method of the 'ContentSavedNotification' to detect which culture caused the Save.
public bool HasSavedCulture(IContent content, string culture);
When handling the Unpublishing notification, it might not work how you would expect. If 'all the variants' are being unpublished at the same time (or the mandatory language is being unpublished, which forces this to occur) then the Unpublishing notification will be published as expected.
public void Handle(ContentUnpublishingNotification notification)
{
foreach (var unPublishedEntity in notification.UnpublishedEntities)
{
// complete unpublishing of entity, all cultures
}
}
However, if only one variant is being unpublished, the Unpublishing event will not be triggered. This is because the content item itself is not fully 'unpublished' by the action. Instead, what occurs is a 'publish' action 'without' the unpublished variant.
You can therefore detect the Unpublishing of a variant in the publishing notification - using the IsUnpublishingCulture extension method of the ContentPublishingNotification
public void Handle(ContentPublishingNotification notification)
{
foreach (var node in notification.PublishedEntities)
{
if (notification.IsUnpublishingCulture(node, "da-DK"))
{
// Bye bye DK!
}
}
}
Again, the Unpublished notification does not get published when a single variant is Unpublished, instead, the Published notification can be used, and the 'HasUnpublishedCulture' extension method of the ContentPublishedNotification can determine which variant being unpublished triggered the publish.
public bool HasUnpublishedCulture(IContent content, string culture);
When handling the ContentPublishingNotification which will be triggered whenever a variant is published (or unpublished - see note in the Unpublishing section above).
You can tell 'which' variant has triggered the publish using a helper method on the ContentPublishingNotification called IsPublishingCulture.
public bool IsPublishingCulture(IContent content, string culture);
For example, you could check which cultures are being published and act accordingly (it could be multiple if multiple checkboxes are checked).
public void Handle(ContentPublishingNotification notification)
{
foreach (var node in notification.PublishedEntities)
{
var publishingCultures = node.AvailableCultures
.Where(culture => notification.IsPublishingCulture(node, culture)).ToList();
var unPublishingCultures = node.AvailableCultures
.Where(culture => notification.IsUnpublishingCulture(node, culture)).ToList();
// or
if (notification.IsPublishingCulture(node, "da-DK"))
{
// Welcome back DK!
}
}
}
In the Published notification you can similarly use the HasPublishedCulture and HasUnpublishedCulture methods of the 'ContentPublishedEventArgs' to detect which culture caused the Publish or the UnPublish if it was only a single non-mandatory variant that was unpublished.
public bool HasPublishedCulture(IContent content, string culture);
public bool HasUnpublishedCulture(ICotnent content, string culture);
In each of these notifications, the entities being Saved, Published, and Unpublished are IContent
entities. There are some useful helper methods on IContent to discover the status of the content item's variant cultures:
bool IsCultureAvailable(string culture);
bool IsCultureEdited(string culture);
bool IsCulturePublished(string culture);
Both the ContentService.Creating and ContentService.Created events were removed, and therefore never moved to notifications. Why? Because these events were not guaranteed to trigger and therefore should not be used. This is because these events would only trigger when the ContentService.CreateContent method was used which is an entirely optional way to create content entities. It is also possible to construct a new content item - which is generally the preferred and consistent way - and therefore the Creating/Created events would not execute when constructing content that way.
Furthermore, there was no reason to listen to the Creating/Created events. They were misleading since they didn't trigger before and after the entity persisted. They are triggered inside the CreateContent method which never persists the entity, it constructs a new content object.
The ContentSavingNotification and ContentSavedNotification will always be published before and after an entity has been persisted. You can determine if an entity is brand new in either of those notifications. In the Saving notification - before the entity is persisted - you can check the entity's HasIdentity property which will be 'false' if it is brand new. In the Saved notification you can check to see if the entity 'remembers being dirty'