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; + } + } + } +}