Skip to content

Commit 2a392e7

Browse files
authored
Merge pull request #7280 from umbraco/custom-error-page
Added Breaking change note and updated Custom error page article
2 parents 05b9d95 + beb2d92 commit 2a392e7

File tree

4 files changed

+76
-60
lines changed

4 files changed

+76
-60
lines changed

16/umbraco-cms/tutorials/custom-error-page.md

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,58 @@ This has been moved to a separate article: [Create a custom maintenance page](cr
2828

2929
## 404 Errors
3030

31+
{% hint style="warning" %}
32+
To follow this guide successfully, ensure you're using Umbraco version 16.1 or later, as it fixes a regression from version 16.0. For more details, see the [Breaking changes](https://our.umbraco.com/download/releases/1610) section in the Release Notes.
33+
{% endhint %}
34+
3135
A 404 error occurs when a requested page cannot be found, usually due to deleted content, a changed URL, or an invalid path. In Umbraco, you can create and configure custom 404 pages using content from the backoffice.
3236

33-
### Create a 404 page in the backoffice
37+
### Create a Page Not Found page in the backoffice
3438

35-
1. Go to the **Settings** section in the Umbraco backoffice.
39+
1. Go to the **Settings** section in the backoffice.
3640
2. Create a new **Document Type with Template**.
37-
3. Name the Document Type *ErrorPage404*.
38-
4. [Optional] Add any custom properties you want — though most 404 pages are static.
41+
3. Name the Document Type *Page Not Found*.
42+
4. [Optional] Add custom properties (for example, title, message), though most 404 pages are static.
3943
5. Click **Save**.
40-
6. Go to the **Templates** folder.
41-
7. Add your custom markup and design for the error page in the template. In this case, *ErrorPage404*.
44+
6. Go to the **Templates** folder and edit the generated template.
45+
7. Add your custom markup and design for the error page in the template.
4246
8. Click **Save**.
4347

44-
### Create a Container for Status Code Pages
48+
### [Optional] Create a Container for Error Pages
49+
50+
You can create a *Page Not Found* page directly in your content tree, or organize it within a container for error pages. Using a container allows for better content organization, especially if you plan to handle multiple status codes (for example, 404, 500, maintenance, and so on). Both options work as long as the page ID is referenced correctly in the `appsettings.json` file.
4551

4652
1. Create a new **Document Type**.
47-
2. Name it **Statuscodes**.
53+
2. Name it *Error Pages Container*.
4854
3. Go to the **Structure** Workspace view.
4955
* Enable **Allow at root**.
50-
* Add the *ErrorPage404* Document Type as an **Allowed child node types**.
56+
* Add the *Page Not Found* Document Type as an **Allowed child node types**.
5157
* Click **Choose**.
5258
4. Click **Save**.
5359

60+
![Container Config](images/container.png)
61+
5462
### Add the Content
5563

5664
1. Go to the **Content** section.
57-
2. Create a new content node based on the **Statuscodes** Document Type and name it **Statuscodes**.
65+
2. Create a new content node based on the *Error Pages Container* Document Type. For example *Home Page*.
5866
3. Click **Save** or **Save and Publish**.
59-
4. Under it, create a child node using the *ErrorPage404* Document Type.
60-
5. Name it *Page 404 Not Found* or similar.
67+
68+
![Parent Content Node](images/content-node.png)
69+
70+
4. Create a child node, using the *Page Not Found* Document Type.
71+
5. Name it *Page Not Found* or similar.
6172
* This will be the content shown when a 404 error occurs.
6273
6. Click **Save** or **Save and Publish**.
6374

75+
![Child Node](images/page-not-found.png)
76+
6477
### Configure the Error Page in `appsettings.json` file
6578

66-
After publishing the 404 page, you’ll need to connect it in your configuration.
79+
After publishing the *Page Not Found* page, connect it in the configuration:
6780

68-
1. Go to the **Info** tab of your *Page 404 Not Found* content item in the Backoffice.
69-
2. Copy the **Id** of the page (for example: 9c2b5196-30cd-4416-ae30-94ac2afb1011).
81+
1. Go to the **Info** tab of the *Page Not Found* content item in the Backoffice.
82+
2. Copy the **Id** of the page (for example: 06cf09c8-c83a-4dd7-84e5-6d98d51e4d12).
7083
3. Go to your project's `appsettings.json` file.
7184
4. Add the `Error404Collection` setting to `Umbraco:CMS:Content`, like shown below:
7285

@@ -78,7 +91,7 @@ After publishing the 404 page, you’ll need to connect it in your configuration
7891
"Error404Collection": [
7992
{
8093
"Culture": "default",
81-
"ContentKey": "9c2b5196-30cd-4416-ae30-94ac2afb1011"
94+
"ContentKey": "06cf09c8-c83a-4dd7-84e5-6d98d51e4d12"
8295
}
8396
]
8497
}
@@ -87,11 +100,11 @@ After publishing the 404 page, you’ll need to connect it in your configuration
87100
}
88101
```
89102

90-
Replace the value for `ContentKey` with the ID of your own 404 page.
103+
Replace the value for `ContentKey` with the ID of your own *Page Not Found* page.
91104

92105
#### Support for Multilingual Sites
93106

94-
You can define different 404 pages for each language or culture (such as `en-us`, `da-dk`, and so on):
107+
You can define different error pages for each language or culture (such as `en-us`, `da-dk`, and so on):
95108

96109
```json
97110
"Error404Collection": [
@@ -112,61 +125,64 @@ Each entry maps a culture to its specific 404 page using the content’s GUID.
112125

113126
It is also possible to set up a 404 error page programmatically using `IContentLastChanceFinder`. To learn more about `IContentLastChanceFinder`, read the [Custom Routing](../implementation/custom-routing/) article.
114127

115-
Before following this example, follow the [Create a 404 page in the backoffice](custom-error-page.md#create-a-404-page-in-the-backoffice) part. The example below will use the *errorPage404* alias of the Document Type to find and display the error page.
128+
Before following this example, follow the [Create a Page Not Found page in the backoffice](#create-a-page-not-found-page-in-the-backoffice) part. The example below will use the *Page Not Found* alias of the Document Type to find and display the error page.
116129

117-
1. Create a new `.cs` file called *Error404Page* at the root of the project.
130+
1. Create a new `.cs` file called *PageNotFound* at the root of the project.
118131
2. Add the following code to the newly created class:
119132

120-
{% code title="Error404Page.cs" lineNumbers="true" %}
133+
{% code title="PageNotFound.cs" lineNumbers="true" %}
121134
```csharp
122135
using Umbraco.Cms.Core.Composing;
123136
using Umbraco.Cms.Core.Routing;
124137
using Umbraco.Cms.Core.Web;
125138

126139
namespace YourProjectNamespace;
127140

128-
public class Error404Page : IContentLastChanceFinder
141+
public class PageNotFound : IContentLastChanceFinder
129142
{
130-
private readonly IUmbracoContextAccessor _contextAccessor;
131-
132-
public Error404Page(IUmbracoContextAccessor contextAccessor)
133-
{
134-
_contextAccessor = contextAccessor;
135-
}
136-
137-
public Task<bool> TryFindContent(IPublishedRequestBuilder request)
138-
{
139-
// In the rare case that an umbracoContext cannot be built from the request,
140-
// we will not be able to find the page
141-
if (_contextAccessor.TryGetUmbracoContext(out var umbracoContext) == false)
142-
{
143-
return Task.FromResult(false);
144-
}
143+
private readonly IServiceProvider _serviceProvider;
145144

146-
// Find the first notFound page at the root level through the published content cache by its documentTypeAlias
147-
// You can make this search as complex as you want, you can return different pages based on anything in the original request
148-
var notFoundPage = umbracoContext.Content?.GetAtRoot().FirstOrDefault(c => c.ContentType.Alias == "errorPage404");
149-
if (notFoundPage == null)
150-
{
151-
return Task.FromResult(false);
152-
}
145+
public PageNotFound(IServiceProvider serviceProvider)
146+
{
147+
_serviceProvider = serviceProvider;
148+
}
153149

154-
//Set the content on the request and mark our search as successful
155-
request.SetPublishedContent(notFoundPage);
156-
request.SetResponseStatus(404);
157-
return Task.FromResult(true);
158-
}
150+
public Task<bool> TryFindContent(IPublishedRequestBuilder request)
151+
{
152+
using var scope = _serviceProvider.CreateScope();
153+
154+
var umbracoContextAccessor = scope.ServiceProvider.GetRequiredService<IUmbracoContextAccessor>();
155+
156+
if (!umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
157+
{
158+
return Task.FromResult(false);
159+
}
160+
161+
var notFoundPage = umbracoContext
162+
.Content
163+
?.GetAtRoot()
164+
.SelectMany(x => x.DescendantsOrSelf())
165+
.FirstOrDefault(c => c.ContentType.Alias == "pageNotFound");
166+
167+
if (notFoundPage == null)
168+
{
169+
return Task.FromResult(false);
170+
}
171+
172+
request.SetPublishedContent(notFoundPage);
173+
request.SetResponseStatus(404);
174+
return Task.FromResult(true);
175+
}
159176
}
160177

161-
// ContentFinders need to be registered into the DI container through a composer
162-
public class Mycomposer : IComposer
178+
// Register the content finder
179+
public class MyComposer : IComposer
163180
{
164-
public void Compose(IUmbracoBuilder builder)
165-
{
166-
builder.SetContentLastChanceFinder<Error404Page>();
167-
}
181+
public void Compose(IUmbracoBuilder builder)
182+
{
183+
builder.SetContentLastChanceFinder<PageNotFound>();
184+
}
168185
}
169-
170186
```
171187
{% endcode %}
172188

@@ -188,10 +204,10 @@ This section guides you in setting up a custom page for handling internal server
188204
6. Add your custom markup and design for the error page in the template. In this case, *ErrorPage500*.
189205
7. Click **Save**.
190206

191-
### Create a Container for Status Code Pages
207+
### [Optional] Create a Container for Error Pages
192208

193209
1. Create a new **Document Type**.
194-
2. Name it **Statuscodes**.
210+
2. Name it **Error Pages Container**.
195211
3. Go to the **Structure** Workspace view.
196212
* Enable **Allow at root**.
197213
* Add the *ErrorPage500* Document Type as an **Allowed child node types**.
@@ -201,9 +217,9 @@ This section guides you in setting up a custom page for handling internal server
201217
### Add the Content
202218

203219
1. Go to the **Content** section.
204-
2. Create a new content node based on the **Statuscodes** Document Type and name it **Statuscodes**.
220+
2. Create a new content node based on the *Error Pages Container* Document Type. For example *Home Page*.
205221
3. Click **Save** or **Save and Publish**.
206-
4. Under it, create a child node using the *ErrorPage500* Document Type.
222+
4. Create a child node, using the *ErrorPage500* Document Type.
207223
5. Name it *Page 500* or similar.
208224
* This will be the content shown when a 500 error occurs.
209225

100 KB
Loading
75.5 KB
Loading
82 KB
Loading

0 commit comments

Comments
 (0)