diff --git a/src/Umbraco.Web.BackOffice/Controllers/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web.BackOffice/Controllers/UmbracoAuthorizedApiController.cs
index 85c92d1139..c232401b78 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/UmbracoAuthorizedApiController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/UmbracoAuthorizedApiController.cs
@@ -1,4 +1,5 @@
-using Umbraco.Web.BackOffice.Filters;
+using Microsoft.AspNetCore.Mvc;
+using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Controllers;
using Umbraco.Web.Common.Filters;
@@ -14,13 +15,12 @@ namespace Umbraco.Web.BackOffice.Controllers
/// before their timeout expires.
///
[IsBackOffice]
- //[UmbracoUserTimeoutFilter] //TODO reintroduce
+ [UmbracoUserTimeoutFilter]
[UmbracoAuthorize]
[DisableBrowserCache]
[UmbracoWebApiRequireHttps]
[CheckIfUserTicketDataIsStale]
- //[UnhandedExceptionLoggerConfiguration] //TODO reintroduce
- //[EnableDetailedErrors] //TODO reintroduce
+ [MiddlewareFilter(typeof(UnhandledExceptionLoggerFilter))]
public abstract class UmbracoAuthorizedApiController : UmbracoApiController
{
diff --git a/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerFilter.cs b/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerFilter.cs
new file mode 100644
index 0000000000..ebea90249c
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerFilter.cs
@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Builder;
+
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ ///
+ /// Applies the UnhandledExceptionLoggerMiddleware to a specific controller
+ /// when used with this attribute [MiddlewareFilter(typeof(UnhandledExceptionLoggerFilter))]
+ /// The middleware will run in the filter pipeline, at the same stage as resource filters
+ ///
+ public class UnhandledExceptionLoggerFilter
+ {
+ public void Configure(IApplicationBuilder applicationBuilder)
+ {
+ applicationBuilder.UseMiddleware();
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerMiddleware.cs b/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerMiddleware.cs
new file mode 100644
index 0000000000..db6162afa8
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Filters/UnhandledExceptionLoggerMiddleware.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core;
+
+namespace Umbraco.Web.BackOffice.Filters
+{
+ ///
+ /// Logs any unhandled exception.
+ ///
+ public class UnhandledExceptionLoggerMiddleware : IMiddleware
+ {
+ private readonly ILogger _logger;
+
+ public UnhandledExceptionLoggerMiddleware(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+ {
+ var requestUri = new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute);
+ // If it's a client side request just call next and don't try to log anything
+ if (requestUri.IsClientSideRequest())
+ {
+ await next(context);
+ }
+ else
+ {
+ // Call the next middleware, and catch any errors that occurs in the rest of the pipeline
+ try
+ {
+ await next(context);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Unhandled controller exception occurred for request '{RequestUrl}'", requestUri.AbsoluteUri);
+ // Throw the error again, just in case it gets handled
+ throw;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
index 1ce0724aea..005a0db36e 100644
--- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
+++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
@@ -7,6 +7,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Services;
using Umbraco.Extensions;
using Umbraco.Web.BackOffice.Controllers;
+using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.BackOffice.Routing;
using Umbraco.Web.BackOffice.Security;
using Umbraco.Web.BackOffice.Services;
@@ -48,6 +49,7 @@ namespace Umbraco.Web.BackOffice.Runtime
"~/"));
composition.RegisterUnique();
+ composition.RegisterUnique();
}
}
}
diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs
index 1b3cde509a..adae78bd74 100644
--- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs
@@ -275,7 +275,7 @@ namespace Umbraco.Extensions
loggingConfiguration,
configuration, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
- var loggerFactory = serviceProvider.GetService();
+ var loggerFactory = services.BuildServiceProvider().GetService();
var umbracoVersion = new UmbracoVersion();
var typeFinder = CreateTypeFinder(loggerFactory, profiler, webHostEnvironment, entryAssembly, typeFinderSettings);
diff --git a/src/Umbraco.Web.Common/Filters/UmbracoUserTimeoutFilterAttribute.cs b/src/Umbraco.Web.Common/Filters/UmbracoUserTimeoutFilterAttribute.cs
new file mode 100644
index 0000000000..2c11b06839
--- /dev/null
+++ b/src/Umbraco.Web.Common/Filters/UmbracoUserTimeoutFilterAttribute.cs
@@ -0,0 +1,36 @@
+using System.Globalization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Umbraco.Extensions;
+
+namespace Umbraco.Web.Common.Filters
+{
+ ///
+ /// This will check if the user making the request is authenticated and if there's an auth ticket tied to the user
+ /// we will add a custom header to the response indicating how many seconds are remaining for the
+ /// user's session. This allows us to keep track of a user's session effectively in the back office.
+ ///
+ public class UmbracoUserTimeoutFilterAttribute : TypeFilterAttribute
+ {
+ public UmbracoUserTimeoutFilterAttribute() : base(typeof(UmbracoUserTimeoutFilter))
+ {
+ }
+
+ private class UmbracoUserTimeoutFilter : IActionFilter
+ {
+ public void OnActionExecuted(ActionExecutedContext context)
+ {
+ //this can occur if an error has already occurred.
+ if (context.HttpContext.Response is null) return;
+
+ var remainingSeconds = context.HttpContext.User.GetRemainingAuthSeconds();
+ context.HttpContext.Response.Headers.Add("X-Umb-User-Seconds", remainingSeconds.ToString(CultureInfo.InvariantCulture));
+ }
+
+ public void OnActionExecuting(ActionExecutingContext context)
+ {
+ // Noop
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 7b224c49b5..5f6ce7fc84 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -237,8 +237,6 @@
-
-
@@ -372,7 +370,6 @@
-
diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoUserTimeoutFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoUserTimeoutFilterAttribute.cs
deleted file mode 100644
index 4221817a17..0000000000
--- a/src/Umbraco.Web/WebApi/Filters/UmbracoUserTimeoutFilterAttribute.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Globalization;
-using System.Web.Http.Filters;
-using Umbraco.Core.Security;
-using Umbraco.Web.Security;
-
-namespace Umbraco.Web.WebApi.Filters
-{
- ///
- /// This will check if the request is authenticated and if there's an auth ticket present we will
- /// add a custom header to the response indicating how many seconds are remaining for the current
- /// user's session. This allows us to keep track of a user's session effectively in the back office.
- ///
- public sealed class UmbracoUserTimeoutFilterAttribute : ActionFilterAttribute
- {
- public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
- {
- base.OnActionExecuted(actionExecutedContext);
-
- //this can occur if an error has already occurred.
- if (actionExecutedContext.Response == null) return;
-
- var httpContextAttempt = actionExecutedContext.Request.TryGetHttpContext();
- if (httpContextAttempt.Success)
- {
-
- var ticket = httpContextAttempt.Result.GetUmbracoAuthTicket();
- if (ticket?.Properties.ExpiresUtc != null && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow)
- {
- var remainingSeconds = httpContextAttempt.Result.GetRemainingAuthSeconds();
- actionExecutedContext.Response.Headers.Add("X-Umb-User-Seconds", remainingSeconds.ToString(CultureInfo.InvariantCulture));
- }
- }
- }
- }
-}
diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
index 7858d6955a..993fd36bc2 100644
--- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
+++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
@@ -21,12 +21,12 @@ namespace Umbraco.Web.WebApi
/// before their timeout expires.
///
[IsBackOffice]
- [UmbracoUserTimeoutFilter]
+ // [UmbracoUserTimeoutFilter] has been migrated to netcore
[UmbracoAuthorize]
[DisableBrowserCache]
// [UmbracoWebApiRequireHttps]
// [CheckIfUserTicketDataIsStale]
- [UnhandedExceptionLoggerConfiguration]
+ // [UnhandedExceptionLoggerConfiguration]
[EnableDetailedErrors]
public abstract class UmbracoAuthorizedApiController : UmbracoApiController
{
diff --git a/src/Umbraco.Web/WebApi/UnhandedExceptionLoggerConfigurationAttribute.cs b/src/Umbraco.Web/WebApi/UnhandedExceptionLoggerConfigurationAttribute.cs
deleted file mode 100644
index 6dc1a49eb1..0000000000
--- a/src/Umbraco.Web/WebApi/UnhandedExceptionLoggerConfigurationAttribute.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web.Http.Controllers;
-using System.Web.Http.ExceptionHandling;
-using System.Web.Http.Filters;
-using Umbraco.Core;
-using Umbraco.Core.Logging;
-
-namespace Umbraco.Web.WebApi
-{
- ///
- /// Adds our unhandled exception logger to the controller's services
- ///
- ///
- /// Important to note that the will only be called if the controller has an ExceptionFilter applied
- /// to it, so to kill two birds with one stone, this class inherits from ExceptionFilterAttribute purely to force webapi to use the
- /// IExceptionLogger (strange)
- ///
- public class UnhandedExceptionLoggerConfigurationAttribute : ExceptionFilterAttribute, IControllerConfiguration
- {
- public virtual void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
- {
- controllerSettings.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger());
- }
-
- }
-}
diff --git a/src/Umbraco.Web/WebApi/UnhandledExceptionLogger.cs b/src/Umbraco.Web/WebApi/UnhandledExceptionLogger.cs
deleted file mode 100644
index 903e333846..0000000000
--- a/src/Umbraco.Web/WebApi/UnhandledExceptionLogger.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Web.Http.ExceptionHandling;
-using Umbraco.Web.Composing;
-using Microsoft.Extensions.Logging;
-
-namespace Umbraco.Web.WebApi
-{
- ///
- /// Used to log unhandled exceptions in webapi controllers
- ///
- public class UnhandledExceptionLogger : ExceptionLogger
- {
- private readonly ILogger _logger;
-
- public UnhandledExceptionLogger()
- : this(Current.Logger)
- {
- }
-
- public UnhandledExceptionLogger(ILogger logger)
- {
- _logger = logger;
- }
-
- public override void Log(ExceptionLoggerContext context)
- {
- if (context != null && context.Exception != null)
- {
- var requestUrl = context.ExceptionContext?.ControllerContext?.Request?.RequestUri?.AbsoluteUri;
- var controllerType = context.ExceptionContext?.ActionContext?.ControllerContext?.Controller?.GetType();
-
- _logger.LogError(context.Exception, "Unhandled controller exception occurred for request '{RequestUrl}'", requestUrl);
- }
- }
-
- }
-}