Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 18/umbraco-cms/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@
* [Determining If an Entity Is New](extend-your-project/server-side-extensions/notifications/determining-new-entity.md)
* [MediaService Notifications Example](extend-your-project/server-side-extensions/notifications/mediaservice-notifications.md)
* [MemberService Notifications Example](extend-your-project/server-side-extensions/notifications/memberservice-notifications.md)
* [RedirectUrlService Notifications Example](extend-your-project/server-side-extensions/notifications/redirecturlservice-notifications.md)
* [Umbraco Application Lifetime Notifications](extend-your-project/server-side-extensions/notifications/umbracoapplicationlifetime-notifications.md)
* [Hot vs. Cold Restarts](extend-your-project/server-side-extensions/notifications/hot-vs-cold-restarts.md)
* [Packages](extend-your-project/packages/README.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ Anytime a document is published and its corresponding _url segment_ changes, Umb

Umbraco registers a new content finder, `ContentFinderByRedirectUrl`, which runs as a normal content finder after the other content finders. It looks for the incoming URL in the database table and, if found, computes the URL of the target document and returns a "301 Redirect". These redirects are considered "permanent". It's good to note that we explicitly set `no-cache` headers on these redirects so that when they change, browsers update the URL immediately. They are a "true" 301, however, and search engines will accept them as such.

## Notifications

The creation and deletion of redirects publish notifications that you can handle. You can use them to log redirect changes or to cancel the creation or deletion of specific redirects.

For handler examples, see the [RedirectUrlService Notifications](../../../../extend-your-project/server-side-extensions/notifications/redirecturlservice-notifications.md) article.

## Enable / Disable / Configure

The 301 Redirect Management feature is enabled by default.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,19 @@ The RelationService provides access to operations involving IRelation and IRelat

<details>

<summary><strong>RedirectUrlService</strong> Notifications</summary>

The RedirectUrlService manages the redirect URLs Umbraco tracks when published content changes its URL. It publishes the following notifications:

* [RedirectUrlSavingNotification](https://apidocs.umbraco.com/v18/csharp/api/Umbraco.Cms.Core.Notifications.RedirectUrlSavingNotification.html)
* [RedirectUrlSavedNotification](https://apidocs.umbraco.com/v18/csharp/api/Umbraco.Cms.Core.Notifications.RedirectUrlSavedNotification.html)
* [RedirectUrlDeletingNotification](https://apidocs.umbraco.com/v18/csharp/api/Umbraco.Cms.Core.Notifications.RedirectUrlDeletingNotification.html)
* [RedirectUrlDeletedNotification](https://apidocs.umbraco.com/v18/csharp/api/Umbraco.Cms.Core.Notifications.RedirectUrlDeletedNotification.html)

</details>

<details>

<summary><strong>UmbracoApplicationLifetime</strong> Notifications</summary>

Represents an Umbraco application lifetime (starting, started, stopping, stopped) notification.
Expand Down Expand Up @@ -277,4 +290,5 @@ Below you can find some articles with some examples using Notifications.
* [Hot vs. cold restarts](hot-vs-cold-restarts.md)
* [MediaService Notifications](mediaservice-notifications.md)
* [MemberService Notifications](memberservice-notifications.md)
* [RedirectUrlService Notifications](redirecturlservice-notifications.md)
* [Umbraco Application Lifetime Notifications](umbracoapplicationlifetime-notifications.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
description: Example of how to use a RedirectUrlService Notification
---

# RedirectUrlService Notifications Example

The RedirectUrlService manages the redirect URLs that Umbraco tracks automatically. A redirect is created when published content changes its URL. For more information, see the [URL Redirect Management](../../../develop-with-umbraco/application-code/backend-and-custom-logic/routing/url-tracking.md) article.

The service publishes four notifications. The "before" notifications are cancelable, which lets a handler stop a redirect from being created or deleted.

| Notification | Published | Cancelable |
| --- | --- | --- |
| `RedirectUrlSavingNotification` | Before a redirect is created or updated | Yes |
| `RedirectUrlSavedNotification` | After a redirect is created or updated | No |
| `RedirectUrlDeletingNotification` | Before a redirect is deleted | Yes |
| `RedirectUrlDeletedNotification` | After a redirect is deleted | No |

The entities in each notification are `IRedirectUrl` objects. Each one exposes the `Url`, `Culture`, `ContentId`, and `ContentKey` of the affected redirect.

## Usage

The following example handles the `RedirectUrlSavingNotification` to stop redirects from being created for a specific part of the site. The redirects being created are available through the `SavedEntities` property.

{% code title="PreventRedirectCreationHandler.cs" %}
```csharp
using System;
using Umbraco.Cms.Core.Notifications;

namespace MySite;

public class PreventRedirectCreationHandler : INotificationHandler<RedirectUrlSavingNotification>
{
public void Handle(RedirectUrlSavingNotification notification)
{
foreach (var redirect in notification.SavedEntities)
{
if (redirect.Url.StartsWith("/example/", StringComparison.OrdinalIgnoreCase))
{
notification.Cancel = true;
}
}
}
}
```
{% endcode %}

{% hint style="info" %}
Canceling a `RedirectUrlSavingNotification` shows no message in the backoffice. Redirects are created silently in the background when content is published. There is no editor action for a message to respond to, so any message added in the handler is discarded.

Canceling a `RedirectUrlDeletingNotification` does show the message. An editor triggers the deletion explicitly from the Redirect URL Management dashboard.
{% endhint %}

## Canceling a redirect deletion

Because deletions are triggered by an editor, a canceled `RedirectUrlDeletingNotification` can return a message explaining why. Use `CancelOperation` to cancel the operation and pass the message at the same time.

{% code title="PreventRedirectDeletionHandler.cs" %}
```csharp
using System;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

namespace MySite;

public class PreventRedirectDeletionHandler : INotificationHandler<RedirectUrlDeletingNotification>
{
public void Handle(RedirectUrlDeletingNotification notification)
{
foreach (var redirect in notification.DeletedEntities)
{
if (redirect.Url.StartsWith("/example/", StringComparison.OrdinalIgnoreCase))
{
notification.CancelOperation(new EventMessage(
"Redirect not deleted",
$"The redirect for {redirect.Url} is protected and cannot be removed.",
EventMessageType.Error));
}
}
}
}
```
{% endcode %}

{% hint style="info" %}
`CancelOperation` cancels the whole notification. When more than one redirect is deleted at once, canceling stops the deletion for all of them, not only the one that matched.
{% endhint %}

## Logging deleted redirects

The "after" notifications cannot be canceled. Use them to react once an operation has completed, for example to write a log entry. The following example handles the `RedirectUrlDeletedNotification` and logs each deleted redirect through the `DeletedEntities` property.

{% code title="LogDeletedRedirectsHandler.cs" %}
```csharp
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Notifications;

namespace MySite;

public class LogDeletedRedirectsHandler : INotificationHandler<RedirectUrlDeletedNotification>
{
private readonly ILogger<LogDeletedRedirectsHandler> _logger;

public LogDeletedRedirectsHandler(ILogger<LogDeletedRedirectsHandler> logger)
=> _logger = logger;

public void Handle(RedirectUrlDeletedNotification notification)
{
foreach (var redirect in notification.DeletedEntities)
{
// Log which redirects were removed.
_logger.LogInformation(
"Redirect for {Url} (culture: {Culture}) was deleted.",
redirect.Url,
redirect.Culture);
}
}
}
```
{% endcode %}

## Registering the handlers

Register the notification handlers in a composer using `AddNotificationHandler`.

{% code title="RedirectUrlNotificationsComposer.cs" %}
```csharp
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Notifications;

namespace MySite;

public class RedirectUrlNotificationsComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddNotificationHandler<RedirectUrlSavingNotification, PreventRedirectCreationHandler>();
builder.AddNotificationHandler<RedirectUrlDeletingNotification, PreventRedirectDeletionHandler>();
builder.AddNotificationHandler<RedirectUrlDeletedNotification, LogDeletedRedirectsHandler>();
}
}
```
{% endcode %}

{% hint style="info" %}
If you call `IRedirectUrlService` directly, use the `RegisterWithStatus`, `DeleteWithStatus`, and `DeleteContentRedirectUrlsWithStatus` methods. These return a `RedirectUrlOperationStatus`, which reports `CancelledByNotification` when a handler cancels the operation. The previous `Register` and `Delete` methods are obsolete and are scheduled for removal in Umbraco 20.
{% endhint %}
Loading