diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
index 59b970ebbc..71b9ac3ef9 100644
--- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
+++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
@@ -181,8 +181,8 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest
app.UseUmbraco()
.WithMiddleware(u =>
{
- u.WithBackOffice();
- u.WithWebsite();
+ u.UseBackOffice();
+ u.UseWebsite();
})
.WithEndpoints(u =>
{
diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.BackOffice.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.BackOffice.cs
index 59cefa0574..13a951b743 100644
--- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.BackOffice.cs
+++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.BackOffice.cs
@@ -12,7 +12,7 @@ using Umbraco.Cms.Web.Common.Extensions;
namespace Umbraco.Extensions
{
///
- /// extensions for Umbraco
+ /// extensions for Umbraco
///
public static partial class UmbracoApplicationBuilderExtensions
{
@@ -21,7 +21,7 @@ namespace Umbraco.Extensions
///
///
///
- public static IUmbracoMiddlewareBuilder WithBackOffice(this IUmbracoMiddlewareBuilder builder)
+ public static IUmbracoApplicationBuilderContext UseBackOffice(this IUmbracoApplicationBuilderContext builder)
{
KeepAliveSettings keepAliveSettings = builder.ApplicationServices.GetRequiredService>().Value;
IHostingEnvironment hostingEnvironment = builder.ApplicationServices.GetRequiredService();
@@ -33,7 +33,7 @@ namespace Umbraco.Extensions
return builder;
}
- public static IUmbracoEndpointBuilder UseBackOfficeEndpoints(this IUmbracoEndpointBuilder app)
+ public static IUmbracoEndpointBuilderContext UseBackOfficeEndpoints(this IUmbracoEndpointBuilderContext app)
{
// NOTE: This method will have been called after UseRouting, UseAuthentication, UseAuthorization
if (app == null)
diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Installer.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Installer.cs
index 2be8c6bb28..d61b955efc 100644
--- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Installer.cs
+++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Installer.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Extensions
///
/// Enables the Umbraco installer
///
- public static IUmbracoEndpointBuilder UseInstallerEndpoints(this IUmbracoEndpointBuilder app)
+ public static IUmbracoEndpointBuilderContext UseInstallerEndpoints(this IUmbracoEndpointBuilderContext app)
{
if (!app.RuntimeState.UmbracoCanBoot())
{
diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Preview.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Preview.cs
index 014f81fe8c..012205575a 100644
--- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Preview.cs
+++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoApplicationBuilder.Preview.cs
@@ -6,11 +6,11 @@ using Umbraco.Cms.Web.Common.ApplicationBuilder;
namespace Umbraco.Extensions
{
///
- /// extensions for Umbraco
+ /// extensions for Umbraco
///
public static partial class UmbracoApplicationBuilderExtensions
{
- public static IUmbracoEndpointBuilder UseUmbracoPreviewEndpoints(this IUmbracoEndpointBuilder app)
+ public static IUmbracoEndpointBuilderContext UseUmbracoPreviewEndpoints(this IUmbracoEndpointBuilderContext app)
{
PreviewRoutes previewRoutes = app.ApplicationServices.GetRequiredService();
previewRoutes.CreateRoutes(app.EndpointRouteBuilder);
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilder.cs b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilder.cs
index 090ef52790..edb103c7c3 100644
--- a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilder.cs
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilder.cs
@@ -1,22 +1,21 @@
using System;
-using Microsoft.AspNetCore.Builder;
-using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Web.Common.ApplicationBuilder
{
public interface IUmbracoApplicationBuilder
{
///
- /// Called to include umbraco middleware
+ /// EXPERT/OPTIONAL call to replace the default middlewares that Umbraco installs by default.
///
- ///
+ ///
///
- IUmbracoApplicationBuilder WithMiddleware(Action configureUmbraco);
+ IUmbracoApplicationBuilder WithCustomDefaultMiddleware(Action configureUmbracoMiddleware);
///
- /// Final call during app building to configure endpoints
+ /// Called to include umbraco middleware
///
- ///
- void WithEndpoints(Action configureUmbraco);
+ ///
+ ///
+ IUmbracoEndpointBuilder WithMiddleware(Action configureUmbracoMiddleware);
}
}
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderContext.cs b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderContext.cs
new file mode 100644
index 0000000000..23346e7aa8
--- /dev/null
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderContext.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Umbraco.Cms.Web.Common.ApplicationBuilder
+{
+
+ public interface IUmbracoApplicationBuilderContext : IUmbracoApplicationBuilderServices
+ {
+ Action RegisterDefaultRequiredMiddleware { get; }
+ }
+}
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoMiddlewareBuilder.cs b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderServices.cs
similarity index 80%
rename from src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoMiddlewareBuilder.cs
rename to src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderServices.cs
index 78d7f28ab9..9df3e29a54 100644
--- a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoMiddlewareBuilder.cs
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoApplicationBuilderServices.cs
@@ -1,13 +1,13 @@
-using System;
+using System;
using Microsoft.AspNetCore.Builder;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Web.Common.ApplicationBuilder
{
- public interface IUmbracoMiddlewareBuilder
+ public interface IUmbracoApplicationBuilderServices
{
- IRuntimeState RuntimeState { get; }
- IServiceProvider ApplicationServices { get; }
IApplicationBuilder AppBuilder { get; }
+ IServiceProvider ApplicationServices { get; }
+ IRuntimeState RuntimeState { get; }
}
}
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilder.cs b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilder.cs
index 31507477ae..58e0b8fec2 100644
--- a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilder.cs
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilder.cs
@@ -1,13 +1,13 @@
-using Microsoft.AspNetCore.Routing;
+using System;
namespace Umbraco.Cms.Web.Common.ApplicationBuilder
{
-
- ///
- /// A builder to allow encapsulating the enabled routing features in Umbraco
- ///
- public interface IUmbracoEndpointBuilder : IUmbracoMiddlewareBuilder
- {
- IEndpointRouteBuilder EndpointRouteBuilder { get; }
+ public interface IUmbracoEndpointBuilder
+ {
+ ///
+ /// Final call during app building to configure endpoints
+ ///
+ ///
+ void WithEndpoints(Action configureUmbraco);
}
}
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilderContext.cs b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilderContext.cs
new file mode 100644
index 0000000000..6122c9ef2e
--- /dev/null
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/IUmbracoEndpointBuilderContext.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Routing;
+
+namespace Umbraco.Cms.Web.Common.ApplicationBuilder
+{
+
+ ///
+ /// A builder to allow encapsulating the enabled routing features in Umbraco
+ ///
+ public interface IUmbracoEndpointBuilderContext : IUmbracoApplicationBuilderServices
+ {
+ IEndpointRouteBuilder EndpointRouteBuilder { get; }
+ }
+}
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoApplicationBuilder.cs b/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoApplicationBuilder.cs
index b7acc45d22..9ea1bee0a1 100644
--- a/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoApplicationBuilder.cs
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoApplicationBuilder.cs
@@ -2,50 +2,130 @@ using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using SixLabors.ImageSharp.Web.DependencyInjection;
using Umbraco.Cms.Core.Services;
+using Umbraco.Extensions;
namespace Umbraco.Cms.Web.Common.ApplicationBuilder
{
///
/// A builder to allow encapsulating the enabled endpoints in Umbraco
///
- internal class UmbracoApplicationBuilder : IUmbracoApplicationBuilder, IUmbracoMiddlewareBuilder
+ public class UmbracoApplicationBuilder : IUmbracoApplicationBuilder, IUmbracoEndpointBuilder, IUmbracoApplicationBuilderContext
{
- public UmbracoApplicationBuilder(IServiceProvider services, IRuntimeState runtimeState, IApplicationBuilder appBuilder)
+ private Action _customMiddlewareRegistration;
+
+ public UmbracoApplicationBuilder(IApplicationBuilder appBuilder)
{
- ApplicationServices = services;
- RuntimeState = runtimeState;
- AppBuilder = appBuilder;
+ ApplicationServices = appBuilder.ApplicationServices;
+ RuntimeState = appBuilder.ApplicationServices.GetRequiredService();
+ AppBuilder = appBuilder ?? throw new ArgumentNullException(nameof(appBuilder));
+ RegisterDefaultRequiredMiddleware = RegisterRequiredMiddleware;
}
public IServiceProvider ApplicationServices { get; }
public IRuntimeState RuntimeState { get; }
public IApplicationBuilder AppBuilder { get; }
+ public Action RegisterDefaultRequiredMiddleware { get; set; }
- public IUmbracoApplicationBuilder WithMiddleware(Action configureUmbraco)
+ ///
+ public IUmbracoApplicationBuilder WithCustomDefaultMiddleware(Action configureUmbracoMiddleware)
{
+ _customMiddlewareRegistration = configureUmbracoMiddleware;
+ return this;
+ }
+
+ ///
+ public IUmbracoEndpointBuilder WithMiddleware(Action configureUmbracoMiddleware)
+ {
+ if (configureUmbracoMiddleware is null)
+ {
+ throw new ArgumentNullException(nameof(configureUmbracoMiddleware));
+ }
+
IOptions startupOptions = ApplicationServices.GetRequiredService>();
+
+ RunPrePipeline(startupOptions.Value);
+
+ if (_customMiddlewareRegistration != null)
+ {
+ _customMiddlewareRegistration(this);
+ }
+ else
+ {
+ RegisterRequiredMiddleware();
+ }
+
RunPostPipeline(startupOptions.Value);
- configureUmbraco(this);
+ configureUmbracoMiddleware(this);
return this;
}
- public void WithEndpoints(Action configureUmbraco)
+ ///
+ public void WithEndpoints(Action configureUmbraco)
{
IOptions startupOptions = ApplicationServices.GetRequiredService>();
RunPreEndpointsPipeline(startupOptions.Value);
AppBuilder.UseEndpoints(endpoints =>
{
- var umbAppBuilder = (IUmbracoEndpointBuilder)ActivatorUtilities.CreateInstance(
+ var umbAppBuilder = (IUmbracoEndpointBuilderContext)ActivatorUtilities.CreateInstance(
ApplicationServices,
new object[] { AppBuilder, endpoints });
configureUmbraco(umbAppBuilder);
});
}
+ ///
+ /// Registers the default required middleware to run Umbraco
+ ///
+ ///
+ private void RegisterRequiredMiddleware()
+ {
+ AppBuilder.UseUmbracoCore();
+ AppBuilder.UseUmbracoRequestLogging();
+
+ // We need to add this before UseRouting so that the UmbracoContext and other middlewares are executed
+ // before endpoint routing middleware.
+ AppBuilder.UseUmbracoRouting();
+
+ AppBuilder.UseStatusCodePages();
+
+ // Important we handle image manipulations before the static files, otherwise the querystring is just ignored.
+ // TODO: Since we are dependent on these we need to register them but what happens when we call this multiple times since we are dependent on this for UseUmbracoBackOffice too?
+ AppBuilder.UseImageSharp();
+ AppBuilder.UseStaticFiles();
+ AppBuilder.UseUmbracoPlugins();
+
+ // UseRouting adds endpoint routing middleware, this means that middlewares registered after this one
+ // will execute after endpoint routing. The ordering of everything is quite important here, see
+ // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-5.0
+ // where we need to have UseAuthentication and UseAuthorization proceeding this call but before
+ // endpoints are defined.
+ AppBuilder.UseRouting();
+ AppBuilder.UseAuthentication();
+ AppBuilder.UseAuthorization();
+
+ // This must come after auth because the culture is based on the auth'd user
+ AppBuilder.UseRequestLocalization();
+
+ // Must be called after UseRouting and before UseEndpoints
+ AppBuilder.UseSession();
+
+ // DO NOT PUT ANY UseEndpoints declarations here!! Those must all come very last in the pipeline,
+ // endpoints are terminating middleware. All of our endpoints are declared in ext of IUmbracoApplicationBuilder
+ }
+
+ private void RunPrePipeline(UmbracoPipelineOptions startupOptions)
+ {
+ foreach (IUmbracoPipelineFilter filter in startupOptions.PipelineFilters)
+ {
+ filter.OnPrePipeline(AppBuilder);
+ }
+ }
+
private void RunPostPipeline(UmbracoPipelineOptions startupOptions)
{
foreach (IUmbracoPipelineFilter filter in startupOptions.PipelineFilters)
diff --git a/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoEndpointBuilder.cs b/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoEndpointBuilder.cs
index 56d856a22a..86e8f3e957 100644
--- a/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoEndpointBuilder.cs
+++ b/src/Umbraco.Web.Common/ApplicationBuilder/UmbracoEndpointBuilder.cs
@@ -8,7 +8,7 @@ namespace Umbraco.Cms.Web.Common.ApplicationBuilder
///
/// A builder to allow encapsulating the enabled endpoints in Umbraco
///
- internal class UmbracoEndpointBuilder : IUmbracoEndpointBuilder
+ internal class UmbracoEndpointBuilder : IUmbracoEndpointBuilderContext
{
public UmbracoEndpointBuilder(IServiceProvider services, IRuntimeState runtimeState, IApplicationBuilder appBuilder, IEndpointRouteBuilder endpointRouteBuilder)
{
diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs
index efc95a59f7..e4ebdf3c0c 100644
--- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs
@@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Serilog.Context;
-using SixLabors.ImageSharp.Web.DependencyInjection;
using StackExchange.Profiling;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
@@ -26,63 +25,7 @@ namespace Umbraco.Extensions
/// Configures and use services required for using Umbraco
///
public static IUmbracoApplicationBuilder UseUmbraco(this IApplicationBuilder app)
- {
- // TODO: Should we do some checks like this to verify that the corresponding "Add" methods have been called for the
- // corresponding "Use" methods?
- // https://github.com/dotnet/aspnetcore/blob/b795ac3546eb3e2f47a01a64feb3020794ca33bb/src/Mvc/Mvc.Core/src/Builder/MvcApplicationBuilderExtensions.cs#L132
- if (app == null)
- {
- throw new ArgumentNullException(nameof(app));
- }
-
- IOptions startupOptions = app.ApplicationServices.GetRequiredService>();
- app.RunPrePipeline(startupOptions.Value);
-
- app.UseUmbracoCore();
- app.UseUmbracoRequestLogging();
-
- // We need to add this before UseRouting so that the UmbracoContext and other middlewares are executed
- // before endpoint routing middleware.
- app.UseUmbracoRouting();
-
- app.UseStatusCodePages();
-
- // Important we handle image manipulations before the static files, otherwise the querystring is just ignored.
- // TODO: Since we are dependent on these we need to register them but what happens when we call this multiple times since we are dependent on this for UseUmbracoBackOffice too?
- app.UseImageSharp();
- app.UseStaticFiles();
- app.UseUmbracoPlugins();
-
- // UseRouting adds endpoint routing middleware, this means that middlewares registered after this one
- // will execute after endpoint routing. The ordering of everything is quite important here, see
- // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-5.0
- // where we need to have UseAuthentication and UseAuthorization proceeding this call but before
- // endpoints are defined.
- app.UseRouting();
- app.UseAuthentication();
- app.UseAuthorization();
-
- // This must come after auth because the culture is based on the auth'd user
- app.UseRequestLocalization();
-
- // Must be called after UseRouting and before UseEndpoints
- app.UseSession();
-
- // DO NOT PUT ANY UseEndpoints declarations here!! Those must all come very last in the pipeline,
- // endpoints are terminating middleware. All of our endpoints are declared in ext of IUmbracoApplicationBuilder
-
- return ActivatorUtilities.CreateInstance(
- app.ApplicationServices,
- new object[] { app });
- }
-
- private static void RunPrePipeline(this IApplicationBuilder app, UmbracoPipelineOptions startupOptions)
- {
- foreach (IUmbracoPipelineFilter filter in startupOptions.PipelineFilters)
- {
- filter.OnPrePipeline(app);
- }
- }
+ => new UmbracoApplicationBuilder(app);
///
/// Returns true if Umbraco is greater than
diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs b/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs
index 0d8c7df72b..74b67c36a6 100644
--- a/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs
+++ b/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs
@@ -11,7 +11,7 @@ namespace Umbraco.Cms.Web.Common.Extensions
///
/// Enables runtime minification for Umbraco
///
- public static IUmbracoEndpointBuilder UseUmbracoRuntimeMinificationEndpoints(this IUmbracoEndpointBuilder app)
+ public static IUmbracoEndpointBuilderContext UseUmbracoRuntimeMinificationEndpoints(this IUmbracoEndpointBuilderContext app)
{
if (app == null)
{
diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs
index 0419a8c0e4..73eeef864f 100644
--- a/src/Umbraco.Web.UI.NetCore/Startup.cs
+++ b/src/Umbraco.Web.UI.NetCore/Startup.cs
@@ -62,8 +62,8 @@ namespace Umbraco.Cms.Web.UI.NetCore
app.UseUmbraco()
.WithMiddleware(u =>
{
- u.WithBackOffice();
- u.WithWebsite();
+ u.UseBackOffice();
+ u.UseWebsite();
})
.WithEndpoints(u =>
{
diff --git a/src/Umbraco.Web.Website/Extensions/UmbracoApplicationBuilder.Website.cs b/src/Umbraco.Web.Website/Extensions/UmbracoApplicationBuilder.Website.cs
index 10cbbfdc4d..4be9f2f2bd 100644
--- a/src/Umbraco.Web.Website/Extensions/UmbracoApplicationBuilder.Website.cs
+++ b/src/Umbraco.Web.Website/Extensions/UmbracoApplicationBuilder.Website.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Extensions
///
///
///
- public static IUmbracoMiddlewareBuilder WithWebsite(this IUmbracoMiddlewareBuilder builder)
+ public static IUmbracoApplicationBuilderContext UseWebsite(this IUmbracoApplicationBuilderContext builder)
{
builder.AppBuilder.UseMiddleware();
return builder;
@@ -26,7 +26,7 @@ namespace Umbraco.Extensions
///
/// Sets up routes for the front-end umbraco website
///
- public static IUmbracoEndpointBuilder UseWebsiteEndpoints(this IUmbracoEndpointBuilder builder)
+ public static IUmbracoEndpointBuilderContext UseWebsiteEndpoints(this IUmbracoEndpointBuilderContext builder)
{
if (builder == null)
{