When you develop an Umbraco website with custom controller you might need a way to specify custom error pages. For example a 404 or 500 page that can be easily displayed as an action result. In my case I have multiple site roots and each site has its own error pages:
- Umbraco
- Site1
- Error Page
- Not Found Page
- Site2
- Error Page
- Not Found Page
- Unauthorized Page
- Site1
The ErrorPage Document Type
Create a simple document type called ErrorPage with one number property called Error Code. The property will store the status code of the page whether it is 404, 500, etc.
The ErrorPage Template
We will define a Template Controller, which will be activated whenever an error page is loaded in the browser. The controller will set the status code to the response.
using System.Web.Mvc; using Umbraco.Web; using Umbraco.Web.Models; using Umbraco.Web.Mvc; namespace Web.Umbraco.Extensions.Controllers.DocumentTypeControllers { public class ErrorPageController : RenderMvcController { public override ActionResult Index(RenderModel model) { Response.StatusCode = model.Content.GetPropertyValue<int>("errorCode"); return base.Index(model); } } }
Calling an ErrorPage from Code
In the following code snippet I have created a custom NotFoundPage action result, which can be returned from an action and will automatically discover the 404 page for the site. You can further extend this by making the NotFoundResult a generic result, which accepts an error code and retrieves the error page for this code.
using System.Linq; using System.Web.Mvc; using umbraco.cms.businesslogic.web; using Umbraco.Web; namespace Web.Umbraco.Extensions.Mvc.ActionResults { public class NotFoundResult : HttpNotFoundResult { public override void ExecuteResult(ControllerContext context) { var domain = Domain.GetRootFromDomain(context.HttpContext.Request.Url.Host); var siteRoot = UmbracoContext.Current.Application.Services.ContentService.GetById(domain); // Discover the 404 page for the current site. var notFoundContent = UmbracoContext.Current.Application.Services.ContentService .GetDescendants(siteRoot) .FirstOrDefault(x => x.ContentType.Alias == "ErrorPage" && x.GetValue<int>("errorCode") == 404); var notFoundUrl = "/not-found"; // Have a default value for the url. if (notFoundContent != null) { var notFoundPublishedContent = UmbracoContext.Current.ContentCache.GetById(notFoundContent.Id); notFoundUrl = notFoundPublishedContent.Url; } context.HttpContext.Server.TransferRequest(notFoundUrl, true); } } }
3 Comments
Rajanikanth (@Rajkant) · August 21, 2014 at 20:29
Thanks for your post. I liked this approach. Could you tell me what other settings/config files i have to modify to get this working.
Thanks,
Raj
Nikolay Arhangelov · August 21, 2014 at 20:47
You should configure your web.config’s customErrors section to use the error page:
Rajanikanth (@Rajkant) · August 21, 2014 at 21:08
Nikolay, I figured out that i commented in umbracoSettings.config. after uncommenting this, your code works fine.