diff --git a/src/Umbraco.Web.BackOffice/ActionExecutedEventArgs.cs b/src/Umbraco.Web.BackOffice/ActionExecutedEventArgs.cs
new file mode 100644
index 0000000000..a2ac5701be
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/ActionExecutedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Umbraco.Web.BackOffice
+{
+ public class ActionExecutedEventArgs : EventArgs
+ {
+ public Controller Controller { get; set; }
+ public object Model { get; set; }
+
+ public ActionExecutedEventArgs(Controller controller, object model)
+ {
+ Controller = controller;
+ Model = model;
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Filters/DisableBrowserCacheAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/DisableBrowserCacheAttribute.cs
new file mode 100644
index 0000000000..e2dc357fa9
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/DisableBrowserCacheAttribute.cs
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Net.Http.Headers;
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ ///
+ /// Ensures that the request is not cached by the browser
+ ///
+ public class DisableBrowserCacheAttribute : ActionFilterAttribute
+ {
+ public override void OnResultExecuting(ResultExecutingContext context)
+ {
+ base.OnResultExecuting(context);
+
+ if (context.HttpContext.Response.StatusCode != 200) return;
+
+ context.HttpContext.Response.GetTypedHeaders().CacheControl =
+ new CacheControlHeaderValue()
+ {
+ NoCache = true,
+ MaxAge = TimeSpan.Zero,
+ MustRevalidate = true,
+ NoStore = true
+ };
+
+ context.HttpContext.Response.Headers[HeaderNames.LastModified] = DateTime.Now.ToString("R"); // Format RFC1123
+ context.HttpContext.Response.Headers[HeaderNames.Pragma] = "no-cache";
+ context.HttpContext.Response.Headers[HeaderNames.Expires] = new DateTime(1990, 1, 1, 0, 0, 0).ToString("R");
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Filters/PreRenderViewActionFilterAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/PreRenderViewActionFilterAttribute.cs
new file mode 100644
index 0000000000..8c8a9a135a
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/PreRenderViewActionFilterAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ public class PreRenderViewActionFilterAttribute : ActionFilterAttribute
+ {
+ public override void OnActionExecuted(ActionExecutedContext context)
+ {
+ if (!(context.Controller is Controller umbController) || !(context.Result is ViewResult result))
+ {
+ return;
+ }
+
+ var model = result.Model;
+ if (model == null)
+ {
+ return;
+ }
+
+ var args = new ActionExecutedEventArgs(umbController, model);
+ OnActionExecuted(args);
+
+ if (args.Model != model)
+ {
+ result.ViewData.Model = args.Model;
+ }
+
+ base.OnActionExecuted(context);
+ }
+
+
+ public static event EventHandler ActionExecuted;
+
+ private static void OnActionExecuted(ActionExecutedEventArgs e)
+ {
+ var handler = ActionExecuted;
+ handler?.Invoke(null, e);
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Filters/StatusCodeResultAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/StatusCodeResultAttribute.cs
new file mode 100644
index 0000000000..870c016b38
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/StatusCodeResultAttribute.cs
@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Mvc.Filters;
+using System.Net;
+using Microsoft.AspNetCore.Diagnostics;
+using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ ///
+ /// Forces the response to have a specific http status code
+ ///
+ public class StatusCodeResultAttribute : ActionFilterAttribute
+ {
+ private readonly HttpStatusCode _statusCode;
+
+ public StatusCodeResultAttribute(HttpStatusCode statusCode)
+ {
+ _statusCode = statusCode;
+ }
+
+ public override void OnActionExecuted(ActionExecutedContext context)
+ {
+ base.OnActionExecuted(context);
+
+ context.HttpContext.Response.StatusCode = (int)_statusCode;
+
+ var disableIisCustomErrors = context.HttpContext.RequestServices.GetService().TrySkipIisCustomErrors;
+ var statusCodePagesFeature = context.HttpContext.Features.Get();
+
+ if (statusCodePagesFeature != null)
+ {
+ // if IIS Custom Errors are disabled, we won't enable the Status Code Pages
+ statusCodePagesFeature.Enabled = !disableIisCustomErrors;
+ }
+ }
+ }
+}