Move to Minimal Hosting Model in a backwards compatible way (#14656)

* Use minimal hosting model

* Make CoreRuntime backward compatible to the old hosting model

* Remove unneccessary methods from interface again

* Pushed the timeout for E2E test to 120 minutes instead of 60

* Updated the preview version from 6 to 7

* Explicitly call BootUmbracoAsync

* Add CreateUmbracoBuilder extension method

* Do not add IRuntime as hosted service when using WebApplication/WebApplicationBuilder

* Set StaticServiceProvider.Instance before booting

* Ensure Umbraco is booted and StaticServiceProvider.Instance is set before configuring middleware

* Do not enable static web assets on production environments

* Removed root namespace from viewImports

---------

Co-authored-by: Andreas Zerbst <andr317c@live.dk>
Co-authored-by: Ronald Barendse <ronald@barend.se>
This commit is contained in:
Bjarke Berg
2023-08-21 12:24:17 +02:00
committed by GitHub
parent 84cd7a163c
commit b1e42e334d
12 changed files with 149 additions and 124 deletions

View File

@@ -142,8 +142,6 @@ public static partial class UmbracoBuilderExtensions
sp,
sp.GetRequiredService<IApplicationDiscriminator>()));
builder.Services.AddHostedService(factory => factory.GetRequiredService<IRuntime>());
builder.Services.AddSingleton<DatabaseSchemaCreatorFactory>();
builder.Services.TryAddEnumerable(ServiceDescriptor
.Singleton<IDatabaseProviderMetadata, CustomConnectionStringDatabaseProviderMetadata>());

View File

@@ -9,6 +9,8 @@ using Serilog.Context;
using StackExchange.Profiling;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Exceptions;
using Umbraco.Cms.Core.Extensions;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Logging.Serilog.Enrichers;
@@ -30,7 +32,21 @@ public static class ApplicationBuilderExtensions
/// Configures and use services required for using Umbraco
/// </summary>
public static IUmbracoApplicationBuilder UseUmbraco(this IApplicationBuilder app)
=> new UmbracoApplicationBuilder(app);
{
// Ensure Umbraco is booted and StaticServiceProvider.Instance is set before continuing
IRuntimeState runtimeState = app.ApplicationServices.GetRequiredService<IRuntimeState>();
if (runtimeState.Level == RuntimeLevel.Unknown)
{
throw new BootFailedException("The runtime level is unknown, please make sure Umbraco is booted by adding `await app.BootUmbracoAsync();` just after `WebApplication app = builder.Build();` in your Program.cs file.");
}
if (StaticServiceProvider.Instance is null)
{
throw new BootFailedException("StaticServiceProvider.Instance is not set, please make sure ConfigureUmbracoDefaults() is added in your Program.cs file.");
}
return new UmbracoApplicationBuilder(app);
}
/// <summary>
/// Returns true if Umbraco <see cref="IRuntimeState" /> is greater than <see cref="RuntimeLevel.BootFailed" />

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
namespace Umbraco.Extensions;
/// <summary>
/// Extension methods for <see cref="WebApplicationBuilder" />.
/// </summary>
public static class WebApplicationBuilderExtensions
{
/// <summary>
/// Creates an <see cref="IUmbracoBuilder" /> and registers basic Umbraco services.
/// </summary>
/// <param name="builder">The builder.</param>
/// <returns>
/// The Umbraco builder.
/// </returns>
public static IUmbracoBuilder CreateUmbracoBuilder(this WebApplicationBuilder builder)
{
// Configure Umbraco defaults, but ignore decorated host builder and
// don't add runtime as hosted service (this is replaced by the explicit BootUmbracoAsync)
builder.Host.ConfigureUmbracoDefaults(false);
// Do not enable static web assets on production environments,
// because the files are already copied to the publish output folder.
if (builder.Configuration.GetRuntimeMode() != RuntimeMode.Production)
{
builder.WebHost.UseStaticWebAssets();
}
return builder.Services.AddUmbraco(builder.Environment, builder.Configuration);
}
}

View File

@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Extensions;
/// <summary>
/// Extension methods for <see cref="WebApplication" />.
/// </summary>
public static class WebApplicationExtensions
{
/// <summary>
/// Starts the <see cref="IRuntime" /> to ensure Umbraco is ready for middleware to be added.
/// </summary>
/// <param name="app">The application.</param>
/// <returns>
/// A <see cref="Task" /> representing the asynchronous operation.
/// </returns>
public static async Task BootUmbracoAsync(this WebApplication app)
{
// Set static IServiceProvider before booting
StaticServiceProvider.Instance = app.Services;
// Ensure the Umbraco runtime is started before middleware is added and stopped when performing a graceful shutdown
IRuntime umbracoRuntime = app.Services.GetRequiredService<IRuntime>();
CancellationTokenRegistration cancellationTokenRegistration = app.Lifetime.ApplicationStopping.Register((_, token) => umbracoRuntime.StopAsync(token), null);
await umbracoRuntime.StartAsync(cancellationTokenRegistration.Token);
}
}

View File

@@ -1,6 +1,8 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Hosting;
// ReSharper disable once CheckNamespace
@@ -15,6 +17,9 @@ public static class HostBuilderExtensions
/// Configures an existing <see cref="IHostBuilder" /> with defaults for an Umbraco application.
/// </summary>
public static IHostBuilder ConfigureUmbracoDefaults(this IHostBuilder builder)
=> builder.ConfigureUmbracoDefaults(true);
internal static IHostBuilder ConfigureUmbracoDefaults(this IHostBuilder builder, bool addRuntimeHostedService)
{
#if DEBUG
builder.ConfigureAppConfiguration(config
@@ -26,10 +31,16 @@ public static class HostBuilderExtensions
#endif
builder.ConfigureLogging(x => x.ClearProviders());
if (addRuntimeHostedService)
{
// Add the Umbraco IRuntime as hosted service
builder.ConfigureServices(services => services.AddHostedService(factory => factory.GetRequiredService<IRuntime>()));
}
return new UmbracoHostBuilderDecorator(builder, OnHostBuilt);
}
// Runs before any IHostedService starts (including generic web host).
// Runs before any IHostedService starts (including generic web host)
private static void OnHostBuilt(IHost host) =>
StaticServiceProvider.Instance = host.Services;
}