Moves some services 'up' to Core, moves core DI registrations 'up' to UmbracoBuilder, moves Composing ext to DependencyInjection namespaces as UmbracoBuilder ext

This commit is contained in:
Shannon
2020-12-24 11:46:17 +11:00
parent f55ace434b
commit 1f6297ad6b
37 changed files with 301 additions and 298 deletions

View File

@@ -51,7 +51,7 @@ namespace Umbraco.Core.DependencyInjection
where TService : class
=> services.Replace(ServiceDescriptor.Singleton(instance));
public static IServiceCollection AddLazySupport(this IServiceCollection services)
internal static IServiceCollection AddLazySupport(this IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient(typeof(Lazy<>), typeof(LazyResolve<>)));
return services;

View File

@@ -3,12 +3,36 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Grid;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Mail;
using Umbraco.Core.Manifest;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Runtime;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Web;
using Umbraco.Web.Cache;
using Umbraco.Web.Editors;
using Umbraco.Web.Features;
using Umbraco.Web.Install;
using Umbraco.Web.Models.PublishedContent;
using Umbraco.Web.Routing;
using Umbraco.Web.Services;
using Umbraco.Web.Templates;
namespace Umbraco.Core.DependencyInjection
{
@@ -79,6 +103,93 @@ namespace Umbraco.Core.DependencyInjection
// Register as singleton to allow injection everywhere.
Services.AddSingleton<ServiceFactory>(p => p.GetService);
Services.AddSingleton<IEventAggregator, EventAggregator>();
Services.AddLazySupport();
Services.AddUnique<IMainDomLock, MainDomSemaphoreLock>();
Services.AddUnique<IIOHelper>(factory =>
{
IHostingEnvironment hostingEnvironment = factory.GetRequiredService<IHostingEnvironment>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return new IOHelperLinux(hostingEnvironment);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return new IOHelperOSX(hostingEnvironment);
}
return new IOHelperWindows(hostingEnvironment);
});
Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RuntimeCache);
Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RequestCache);
Services.AddUnique<IProfilingLogger, ProfilingLogger>();
Services.AddUnique<IUmbracoVersion, UmbracoVersion>();
this.AddNotificationHandler<UmbracoApplicationStarting, EssentialDirectoryCreator>();
Services.AddSingleton<ManifestWatcher>();
this.AddNotificationHandler<UmbracoApplicationStarting, AppPluginsManifestWatcherNotificationHandler>();
Services.AddUnique<InstallStatusTracker>();
// by default, register a noop factory
Services.AddUnique<IPublishedModelFactory, NoopPublishedModelFactory>();
Services.AddUnique<ICultureDictionaryFactory, DefaultCultureDictionaryFactory>();
Services.AddSingleton(f => f.GetRequiredService<ICultureDictionaryFactory>().CreateDictionary());
Services.AddUnique<UriUtility>();
Services.AddUnique<IDashboardService, DashboardService>();
// will be injected in controllers when needed to invoke rest endpoints on Our
Services.AddUnique<IInstallationService, InstallationService>();
Services.AddUnique<IUpgradeService, UpgradeService>();
// Grid config is not a real config file as we know them
Services.AddUnique<IGridConfig, GridConfig>();
Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
Services.AddUnique<ISiteDomainHelper, SiteDomainHelper>();
Services.AddUnique<HtmlLocalLinkParser>();
Services.AddUnique<HtmlImageSourceParser>();
Services.AddUnique<HtmlUrlParser>();
// register properties fallback
Services.AddUnique<IPublishedValueFallback, PublishedValueFallback>();
Services.AddUnique<UmbracoFeatures>();
// register published router
Services.AddUnique<IPublishedRouter, PublishedRouter>();
Services.AddUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();
Services.AddUnique<IEventMessagesAccessor, HybridEventMessagesAccessor>();
Services.AddUnique<ITreeService, TreeService>();
Services.AddUnique<ISectionService, SectionService>();
Services.AddUnique<ISmsSender, NotImplementedSmsSender>();
Services.AddUnique<IEmailSender, NotImplementedEmailSender>();
// register distributed cache
Services.AddUnique(f => new DistributedCache(f.GetRequiredService<IServerMessenger>(), f.GetRequiredService<CacheRefresherCollection>()));
// register the http context and umbraco context accessors
// we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
// we have no http context, eg when booting Umbraco or in background threads, so instead
// let's use an hybrid accessor that can fall back to a ThreadStatic context.
Services.AddUnique<IUmbracoContextAccessor, HybridUmbracoContextAccessor>();
Services.AddUnique<LegacyPasswordSecurity>();
Services.AddUnique<UserEditorAuthorizationHelper>();
Services.AddUnique<ContentPermissions>();
Services.AddUnique<MediaPermissions>();
}
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.HealthCheck;
using Umbraco.Core.Mail;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Infrastructure.HealthCheck;

View File

@@ -1,7 +1,7 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
using Umbraco.Core.Models;
namespace Umbraco.Core
namespace Umbraco.Core.Mail
{
/// <summary>
/// Simple abstraction to send an email message

View File

@@ -1,6 +1,6 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Umbraco.Core
namespace Umbraco.Core.Mail
{
/// <summary>
/// Service to send an SMS

View File

@@ -0,0 +1,12 @@
using System;
using System.Threading.Tasks;
using Umbraco.Core.Models;
namespace Umbraco.Core.Mail
{
internal class NotImplementedEmailSender : IEmailSender
{
public Task SendAsync(EmailMessage message)
=> throw new NotImplementedException("To send an Email ensure IEmailSender is implemented with a custom implementation");
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System;
using System.Threading.Tasks;
namespace Umbraco.Core
namespace Umbraco.Core.Mail
{
/// <summary>
/// An <see cref="ISmsSender"/> that throws <see cref="NotImplementedException"/>

View File

@@ -2,12 +2,11 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.Manifest;
namespace Umbraco.Infrastructure.Runtime
namespace Umbraco.Core.Runtime
{
/// <summary>
/// Starts monitoring AppPlugins directory during debug runs, to restart site when a plugin manifest changes.

View File

@@ -1,13 +1,12 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
namespace Umbraco.Infrastructure.Runtime
namespace Umbraco.Core.Runtime
{
public class EssentialDirectoryCreator : INotificationHandler<UmbracoApplicationStarting>
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Runtime
_logger = logger;
}
//WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
// WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
public Task ListenAsync() => _signal.WaitOneAsync();
public Task<bool> AcquireLockAsync(int millisecondsTimeout)
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime
// if more than 1 instance reach that point, one will get the lock
// and the other one will timeout, which is accepted
//This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
// This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
try
{
_lockRelease = _systemLock.Lock(millisecondsTimeout);

View File

@@ -1,8 +1,8 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
namespace Umbraco.Core.Services.Implement
namespace Umbraco.Core.Services
{
public class InstallationService : IInstallationService
{

View File

@@ -1,10 +1,9 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
using Semver;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Services;
namespace Umbraco.Core
namespace Umbraco.Core.Services
{
public class UpgradeService : IUpgradeService
{

View File

@@ -1,36 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
using Umbraco.Web.Install;
using Umbraco.Web.Install.InstallSteps;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Composing.CompositionExtensions
{
public static class Installer
{
public static IUmbracoBuilder ComposeInstaller(this IUmbracoBuilder builder)
{
// register the installer steps
builder.Services.AddScoped<InstallSetupStep,NewInstallStep>();
builder.Services.AddScoped<InstallSetupStep,UpgradeStep>();
builder.Services.AddScoped<InstallSetupStep,FilePermissionsStep>();
builder.Services.AddScoped<InstallSetupStep,DatabaseConfigureStep>();
builder.Services.AddScoped<InstallSetupStep,DatabaseInstallStep>();
builder.Services.AddScoped<InstallSetupStep,DatabaseUpgradeStep>();
// TODO: Add these back once we have a compatible Starter kit
// composition.Services.AddScoped<InstallSetupStep,StarterKitDownloadStep>();
// composition.Services.AddScoped<InstallSetupStep,StarterKitInstallStep>();
// composition.Services.AddScoped<InstallSetupStep,StarterKitCleanupStep>();
builder.Services.AddScoped<InstallSetupStep,CompleteInstallStep>();
builder.Services.AddTransient<InstallStepCollection>();
builder.Services.AddUnique<InstallHelper>();
return builder;
}
}
}

View File

@@ -1,18 +1,16 @@
using System;
using System.Runtime.InteropServices;
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Grid;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Dashboards;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.Install;
using Umbraco.Core.Mail;
using Umbraco.Core.Manifest;
using Umbraco.Core.Media;
using Umbraco.Core.Migrations;
@@ -20,16 +18,14 @@ using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Packaging;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.Validators;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Runtime;
using Umbraco.Core.Scoping;
using Umbraco.Core.Security;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core.Templates;
using Umbraco.Examine;
using Umbraco.Infrastructure.Examine;
@@ -37,10 +33,8 @@ using Umbraco.Infrastructure.Media;
using Umbraco.Infrastructure.Runtime;
using Umbraco.Web;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Editors;
using Umbraco.Web.Features;
using Umbraco.Web.HealthCheck;
using Umbraco.Web.HealthCheck.NotificationMethods;
using Umbraco.Web.Install;
@@ -54,8 +48,6 @@ using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Search;
using Umbraco.Web.Sections;
using Umbraco.Web.Services;
using Umbraco.Web.Templates;
using Umbraco.Web.Trees;
using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter;
@@ -66,7 +58,7 @@ namespace Umbraco.Infrastructure.DependencyInjection
/*
* TODO: Many of these things are not "Core" services and are probably not required to run
*
*
* This should be split up:
* - Distributed Cache
* - BackOffice
@@ -83,19 +75,25 @@ namespace Umbraco.Infrastructure.DependencyInjection
* - Front End
*/
/// <summary>
/// Adds all core Umbraco services required to run which may be replaced later in the pipeline
/// </summary>
public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder)
{
builder.AddNotificationHandler<UmbracoApplicationStarting, EssentialDirectoryCreator>();
builder.AddMainDom();
builder.Services.AddSingleton<ManifestWatcher>();
builder.AddNotificationHandler<UmbracoApplicationStarting, AppPluginsManifestWatcherNotificationHandler>();
builder.Services.AddUnique<IUmbracoDatabaseFactory, UmbracoDatabaseFactory>();
builder.Services.AddUnique(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().CreateDatabase());
builder.Services.AddUnique(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().SqlContext);
builder.Services.AddUnique<IRuntimeState, RuntimeState>();
builder.Services.AddUnique<IRuntime, CoreRuntime>();
// composers
builder
.ComposeRepositories()
.ComposeServices()
.ComposeCoreMappingProfiles()
.ComposeFileSystems();
.AddRepositories()
.AddServices()
.AddCoreMappingProfiles()
.AddFileSystems();
// register persistence mappers - required by database factory so needs to be done here
// means the only place the collection can be modified is in a runtime - afterwards it
@@ -110,7 +108,6 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.Services.AddUnique<IJsonSerializer, JsonNetSerializer>();
builder.Services.AddUnique<IConfigurationEditorJsonSerializer, ConfigurationEditorJsonSerializer>();
builder.Services.AddUnique<IMenuItemCollectionFactory, MenuItemCollectionFactory>();
builder.Services.AddUnique<InstallStatusTracker>();
// register database builder
// *not* a singleton, don't want to keep it around
@@ -146,41 +143,6 @@ namespace Umbraco.Infrastructure.DependencyInjection
// references to media item/s
builder.DataValueReferenceFactories();
// register a server registrar, by default it's the db registrar
builder.Services.AddUnique(f =>
{
var globalSettings = f.GetRequiredService<IOptions<GlobalSettings>>().Value;
// TODO: we still register the full IServerMessenger because
// even on 1 single server we can have 2 concurrent app domains
var singleServer = globalSettings.DisableElectionForSingleServer;
return singleServer
? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService<IRequestAccessor>())
: new DatabaseServerRegistrar(
new Lazy<IServerRegistrationService>(f.GetRequiredService<IServerRegistrationService>));
});
// by default we'll use the database server messenger with default options (no callbacks),
// this will be overridden by the db thing in the corresponding components in the web
// project
builder.Services.AddUnique<IServerMessenger>(factory
=> new DatabaseServerMessenger(
factory.GetRequiredService<IMainDom>(),
factory.GetRequiredService<IScopeProvider>(),
factory.GetRequiredService<IUmbracoDatabaseFactory>(),
factory.GetRequiredService<IProfilingLogger>(),
factory.GetRequiredService<ILogger<DatabaseServerMessenger>>(),
factory.GetRequiredService<IServerRegistrar>(),
true,
new DatabaseServerMessengerCallbacks(),
factory.GetRequiredService<IHostingEnvironment>(),
factory.GetRequiredService<CacheRefresherCollection>(),
factory.GetRequiredService<IOptions<GlobalSettings>>()
));
builder.CacheRefreshers()
.Add(() => builder.TypeLoader.GetCacheRefreshers());
builder.PackageActions()
.Add(() => builder.TypeLoader.GetPackageActions());
@@ -197,43 +159,20 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.Services.AddUnique<IMigrationBuilder>(factory => new MigrationBuilder(factory));
// by default, register a noop factory
builder.Services.AddUnique<IPublishedModelFactory, NoopPublishedModelFactory>();
builder.Services.AddUnique<IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();
builder.SetCultureDictionaryFactory<DefaultCultureDictionaryFactory>();
builder.Services.AddSingleton(f => f.GetRequiredService<ICultureDictionaryFactory>().CreateDictionary());
builder.Services.AddUnique<UriUtility>();
// register the published snapshot accessor - the "current" published snapshot is in the umbraco context
builder.Services.AddUnique<IPublishedSnapshotAccessor, UmbracoContextPublishedSnapshotAccessor>();
builder.Services.AddUnique<IVariationContextAccessor, HybridVariationContextAccessor>();
builder.Services.AddUnique<IDashboardService, DashboardService>();
// register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards
builder.Dashboards()
.Add(builder.TypeLoader.GetTypes<IDashboard>());
// will be injected in controllers when needed to invoke rest endpoints on Our
builder.Services.AddUnique<IInstallationService, InstallationService>();
builder.Services.AddUnique<IUpgradeService, UpgradeService>();
// Grid config is not a real config file as we know them
builder.Services.AddUnique<IGridConfig, GridConfig>();
// Config manipulator
builder.Services.AddUnique<IConfigManipulator, JsonConfigManipulator>();
// register the umbraco context factory
// composition.Services.AddUnique<IUmbracoContextFactory, UmbracoContextFactory>();
builder.Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
builder.Services.AddUnique<HtmlLocalLinkParser>();
builder.Services.AddUnique<HtmlImageSourceParser>();
builder.Services.AddUnique<HtmlUrlParser>();
builder.Services.AddUnique<RichTextEditorPastedImages>();
builder.Services.AddUnique<BlockEditorConverter>();
@@ -254,15 +193,8 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.MediaUrlProviders()
.Append<DefaultMediaUrlProvider>();
builder.Services.AddUnique<ISiteDomainHelper, SiteDomainHelper>();
// register properties fallback
builder.Services.AddUnique<IPublishedValueFallback, PublishedValueFallback>();
builder.Services.AddUnique<IImageUrlGenerator, ImageSharpImageUrlGenerator>();
builder.Services.AddUnique<UmbracoFeatures>();
builder.Actions()
.Add(() => builder.TypeLoader.GetTypes<IAction>());
@@ -311,9 +243,6 @@ namespace Umbraco.Infrastructure.DependencyInjection
.Append<ContentTypePermissionsContentAppFactory>()
.Append<ContentTypeTemplatesContentAppFactory>();
// register published router
builder.Services.AddUnique<IPublishedRouter, PublishedRouter>();
// register *all* checks, except those marked [HideFromTypeFinder] of course
builder.Services.AddUnique<IMarkdownToHtmlConverter, MarkdownToHtmlConverter>();
builder.HealthChecks()
@@ -325,12 +254,14 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.Services.AddUnique<IContentLastChanceFinder, ContentFinderByConfigured404>();
builder.ContentFinders()
// all built-in finders in the correct order,
// devs can then modify this list on application startup
.Append<ContentFinderByPageIdQuery>()
.Append<ContentFinderByUrl>()
.Append<ContentFinderByIdPath>()
//.Append<ContentFinderByUrlAndTemplate>() // disabled, this is an odd finder
// .Append<ContentFinderByUrlAndTemplate>() // disabled, this is an odd finder
.Append<ContentFinderByUrlAlias>()
.Append<ContentFinderByRedirectUrl>();
@@ -339,26 +270,13 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.SearchableTrees()
.Add(() => builder.TypeLoader.GetTypes<ISearchableTree>());
// replace some services
builder.Services.AddUnique<IEventMessagesFactory, DefaultEventMessagesFactory>();
builder.Services.AddUnique<IEventMessagesAccessor, HybridEventMessagesAccessor>();
builder.Services.AddUnique<ITreeService, TreeService>();
builder.Services.AddUnique<ISectionService, SectionService>();
// replace
builder.Services.AddUnique<IEmailSender, EmailSender>();
builder.Services.AddUnique<ISmsSender, NotImplementedSmsSender>();
builder.Services.AddUnique<IExamineManager, ExamineManager>();
// register distributed cache
builder.Services.AddUnique(f => new DistributedCache(f.GetRequiredService<IServerMessenger>(), f.GetRequiredService<CacheRefresherCollection>()));
builder.Services.AddScoped<ITagQuery, TagQuery>();
builder.Services.AddUnique<HtmlLocalLinkParser>();
builder.Services.AddUnique<HtmlUrlParser>();
builder.Services.AddUnique<HtmlImageSourceParser>();
builder.Services.AddUnique<RichTextEditorPastedImages>();
builder.Services.AddUnique<IUmbracoTreeSearcherFields, UmbracoTreeSearcherFields>();
builder.Services.AddScoped<IPublishedContentQuery>(factory =>
{
@@ -366,14 +284,6 @@ namespace Umbraco.Infrastructure.DependencyInjection
return new PublishedContentQuery(umbCtx.UmbracoContext.PublishedSnapshot, factory.GetRequiredService<IVariationContextAccessor>(), factory.GetRequiredService<IExamineManager>());
});
builder.Services.AddUnique<IPublishedUrlProvider, UrlProvider>();
// register the http context and umbraco context accessors
// we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
// we have no http context, eg when booting Umbraco or in background threads, so instead
// let's use an hybrid accessor that can fall back to a ThreadStatic context.
builder.Services.AddUnique<IUmbracoContextAccessor, HybridUmbracoContextAccessor>();
// register accessors for cultures
builder.Services.AddUnique<IDefaultCultureAccessor, DefaultCultureAccessor>();
@@ -389,17 +299,33 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.Services.AddUnique<ICronTabParser, NCronTabParser>();
builder.Services.AddUnique(factory => new LegacyPasswordSecurity());
builder.Services.AddUnique<UserEditorAuthorizationHelper>();
builder.Services.AddUnique<ContentPermissions>();
builder.Services.AddUnique<MediaPermissions>();
builder.Services.AddUnique<IImageDimensionExtractor, ImageDimensionExtractor>();
builder.Services.AddUnique<PackageDataInstallation>();
return builder;
}
private static IUmbracoBuilder AddMainDom(this IUmbracoBuilder builder)
{
builder.Services.AddUnique<IMainDom, MainDom>();
builder.Services.AddUnique<IMainDomLock>(factory =>
{
var globalSettings = factory.GetRequiredService<IOptions<GlobalSettings>>().Value;
var connectionStrings = factory.GetRequiredService<IOptions<ConnectionStrings>>().Value;
var hostingEnvironment = factory.GetRequiredService<IHostingEnvironment>();
var dbCreator = factory.GetRequiredService<IDbProviderFactoryCreator>();
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var loggerFactory = factory.GetRequiredService<ILoggerFactory>();
return globalSettings.MainDomLock.Equals("SqlMainDomLock") || isWindows == false
? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger<SqlMainDomLock>(), loggerFactory, globalSettings, connectionStrings, dbCreator, hostingEnvironment)
: new MainDomSemaphoreLock(loggerFactory.CreateLogger<MainDomSemaphoreLock>(), hostingEnvironment);
});
return builder;
}
}
}

View File

@@ -1,8 +1,11 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Core.Sync;
using Umbraco.Infrastructure.Cache;
@@ -29,6 +32,21 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.SetServerMessenger<BatchedDatabaseServerMessenger>();
builder.AddNotificationHandler<UmbracoApplicationStarting, DatabaseServerMessengerNotificationHandler>();
// TODO: We don't need server registrar anymore
// register a server registrar, by default it's the db registrar
builder.Services.AddUnique(f =>
{
var globalSettings = f.GetRequiredService<IOptions<GlobalSettings>>().Value;
// TODO: we still register the full IServerMessenger because
// even on 1 single server we can have 2 concurrent app domains
var singleServer = globalSettings.DisableElectionForSingleServer;
return singleServer
? (IServerRegistrar)new SingleServerRegistrar(f.GetRequiredService<IRequestAccessor>())
: new DatabaseServerRegistrar(
new Lazy<IServerRegistrationService>(f.GetRequiredService<IServerRegistrationService>));
});
builder.CacheRefreshers()
.Add(() => builder.TypeLoader.GetCacheRefreshers());

View File

@@ -1,17 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Strings;
using Umbraco.Infrastructure.DependencyInjection;
namespace Umbraco.Core.Composing.CompositionExtensions
namespace Umbraco.Infrastructure.DependencyInjection
{
internal static class FileSystems
public static partial class UmbracoBuilderExtensions
{
/*
* HOW TO REPLACE THE MEDIA UNDERLYING FILESYSTEM
@@ -35,16 +33,16 @@ namespace Umbraco.Core.Composing.CompositionExtensions
*
*/
public static IUmbracoBuilder ComposeFileSystems(this IUmbracoBuilder builder)
internal static IUmbracoBuilder AddFileSystems(this IUmbracoBuilder builder)
{
// register FileSystems, which manages all filesystems
// it needs to be registered (not only the interface) because it provides additional
// functionality eg for scoping, and is injected in the scope provider - whereas the
// interface is really for end-users to get access to filesystems.
builder.Services.AddUnique(factory => factory.CreateInstance<Core.IO.FileSystems>(factory));
builder.Services.AddUnique(factory => factory.CreateInstance<FileSystems>(factory));
// register IFileSystems, which gives access too all filesystems
builder.Services.AddUnique<IFileSystems>(factory => factory.GetRequiredService<Core.IO.FileSystems>());
builder.Services.AddUnique<IFileSystems>(factory => factory.GetRequiredService<FileSystems>());
// register the scheme for media paths
builder.Services.AddUnique<IMediaPathScheme, UniqueMediaPathScheme>();

View File

@@ -0,0 +1,36 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.DependencyInjection;
using Umbraco.Web.Install;
using Umbraco.Web.Install.InstallSteps;
using Umbraco.Web.Install.Models;
namespace Umbraco.Infrastructure.DependencyInjection
{
public static partial class UmbracoBuilderExtensions
{
/// <summary>
/// Adds the services for the Umbraco installer
/// </summary>
public static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder)
{
// register the installer steps
builder.Services.AddScoped<InstallSetupStep, NewInstallStep>();
builder.Services.AddScoped<InstallSetupStep, UpgradeStep>();
builder.Services.AddScoped<InstallSetupStep, FilePermissionsStep>();
builder.Services.AddScoped<InstallSetupStep, DatabaseConfigureStep>();
builder.Services.AddScoped<InstallSetupStep, DatabaseInstallStep>();
builder.Services.AddScoped<InstallSetupStep, DatabaseUpgradeStep>();
// TODO: Add these back once we have a compatible Starter kit
// composition.Services.AddScoped<InstallSetupStep,StarterKitDownloadStep>();
// composition.Services.AddScoped<InstallSetupStep,StarterKitInstallStep>();
// composition.Services.AddScoped<InstallSetupStep,StarterKitCleanupStep>();
builder.Services.AddScoped<InstallSetupStep, CompleteInstallStep>();
builder.Services.AddTransient<InstallStepCollection>();
builder.Services.AddUnique<InstallHelper>();
return builder;
}
}
}

View File

@@ -4,17 +4,14 @@ using Umbraco.Core.Mapping;
using Umbraco.Core.Security;
using Umbraco.Web.Models.Mapping;
namespace Umbraco.Core.Composing.CompositionExtensions
namespace Umbraco.Infrastructure.DependencyInjection
{
public static class CoreMappingProfiles
public static partial class UmbracoBuilderExtensions
{
/// <summary>
/// Registers the core Umbraco mapper definitions
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IUmbracoBuilder ComposeCoreMappingProfiles(this IUmbracoBuilder builder)
public static IUmbracoBuilder AddCoreMappingProfiles(this IUmbracoBuilder builder)
{
builder.Services.AddUnique<UmbracoMapper>();
@@ -34,8 +31,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
.Add<TemplateMapDefinition>()
.Add<UserMapDefinition>()
.Add<LanguageMapDefinition>()
.Add<IdentityMapDefinition>()
;
.Add<IdentityMapDefinition>();
builder.Services.AddTransient<CommonMapper>();
builder.Services.AddTransient<MemberTabsAndPropertiesMapper>();

View File

@@ -1,15 +1,18 @@
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.Repositories.Implement;
namespace Umbraco.Core.Composing.CompositionExtensions
namespace Umbraco.Infrastructure.DependencyInjection
{
/// <summary>
/// Composes repositories.
/// </summary>
internal static class Repositories
public static partial class UmbracoBuilderExtensions
{
public static IUmbracoBuilder ComposeRepositories(this IUmbracoBuilder builder)
/// <summary>
/// Adds the Umbraco repositories
/// </summary>
internal static IUmbracoBuilder AddRepositories(this IUmbracoBuilder builder)
{
// repositories
builder.Services.AddUnique<IAuditRepository, AuditRepository>();

View File

@@ -1,9 +1,10 @@
using System;
using System;
using System.IO;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
@@ -15,16 +16,15 @@ using Umbraco.Core.Routing;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Composing.CompositionExtensions
namespace Umbraco.Infrastructure.DependencyInjection
{
internal static class Services
public static partial class UmbracoBuilderExtensions
{
public static IUmbracoBuilder ComposeServices(this IUmbracoBuilder builder)
/// <summary>
/// Adds Umbraco services
/// </summary>
internal static IUmbracoBuilder AddServices(this IUmbracoBuilder builder)
{
// register a transient messages factory, which will be replaced by the web
// boot manager when running in a web context
builder.Services.AddUnique<IEventMessagesFactory, TransientEventMessagesFactory>();
// register the service context
builder.Services.AddUnique<ServiceContext>();
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
builder.Services.AddUnique<IExternalLoginService, ExternalLoginService>();
builder.Services.AddUnique<IRedirectUrlService, RedirectUrlService>();
builder.Services.AddUnique<IConsentService, ConsentService>();
builder.Services.AddTransient<LocalizedTextServiceFileSources>(SourcesFactory);
builder.Services.AddTransient(SourcesFactory);
builder.Services.AddUnique<ILocalizedTextService>(factory => new LocalizedTextService(
factory.GetRequiredService<Lazy<LocalizedTextServiceFileSources>>(),
factory.GetRequiredService<ILogger<LocalizedTextService>>()));
@@ -82,9 +82,6 @@ namespace Umbraco.Core.Composing.CompositionExtensions
/// <summary>
/// Creates an instance of PackagesRepository for either the ICreatedPackagesRepository or the IInstalledPackagesRepository
/// </summary>
/// <param name="factory"></param>
/// <param name="packageRepoFileName"></param>
/// <returns></returns>
private static PackagesRepository CreatePackageRepository(IServiceProvider factory, string packageRepoFileName)
=> new PackagesRepository(
factory.GetRequiredService<IContentService>(),
@@ -106,9 +103,9 @@ namespace Umbraco.Core.Composing.CompositionExtensions
{
var hostingEnvironment = container.GetRequiredService<IHostingEnvironment>();
var globalSettings = container.GetRequiredService<IOptions<GlobalSettings>>().Value;
var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath , "config","lang")));
var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath, "config", "lang")));
var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins));
var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config ,"lang")));
var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config, "lang")));
var pluginLangFolders = appPlugins.Exists == false
? Enumerable.Empty<LocalizedTextServiceSupplementaryFileSource>()
@@ -117,7 +114,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
.SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly))
.Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false));
//user defined langs that overwrite the default, these should not be used by plugin creators
// user defined langs that overwrite the default, these should not be used by plugin creators
var userLangFolders = configLangFolder.Exists == false
? Enumerable.Empty<LocalizedTextServiceSupplementaryFileSource>()
: configLangFolder

View File

@@ -7,6 +7,7 @@ using MimeKit;
using MimeKit.Text;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Events;
using Umbraco.Core.Mail;
using Umbraco.Core.Models;
using SmtpClient = MailKit.Net.Smtp.SmtpClient;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Drawing;
using System.IO;
using Umbraco.Core;
@@ -18,7 +18,7 @@ namespace Umbraco.Web.Media
/// use potentially large amounts of memory.</remarks>
public ImageSize GetDimensions(Stream stream)
{
//Try to load with exif
// Try to load with exif
try
{
if (ExifImageDimensionExtractor.TryGetDimensions(stream, out var width, out var height))
@@ -28,12 +28,13 @@ namespace Umbraco.Web.Media
}
catch
{
//We will just swallow, just means we can't read exif data, we don't want to log an error either
// We will just swallow, just means we can't read exif data, we don't want to log an error either
}
//we have no choice but to try to read in via GDI
// we have no choice but to try to read in via GDI
try
{
// TODO: We should be using ImageSharp for this
using (var image = Image.FromStream(stream))
{
var fileWidth = image.Width;
@@ -43,7 +44,7 @@ namespace Umbraco.Web.Media
}
catch (Exception)
{
//We will just swallow, just means we can't read via GDI, we don't want to log an error either
// We will just swallow, just means we can't read via GDI, we don't want to log an error either
}
return new ImageSize(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -17,16 +17,11 @@ namespace Umbraco.Core.Packaging
private readonly IPackageActionRunner _packageActionRunner;
private readonly DirectoryInfo _applicationRootFolder;
/// <summary>
/// Constructor
/// Initializes a new instance of the <see cref="PackageInstallation"/> class.
/// </summary>
/// <param name="packageDataInstallation"></param>
/// <param name="packageFileInstallation"></param>
/// <param name="parser"></param>
/// <param name="packageActionRunner"></param>
/// <param name="hostingEnvironment"></param>
public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner,
IHostingEnvironment hostingEnvironment)
public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, IHostingEnvironment hostingEnvironment)
{
_packageExtraction = new PackageExtraction();
_packageFileInstallation = packageFileInstallation ?? throw new ArgumentNullException(nameof(packageFileInstallation));

View File

@@ -14,6 +14,7 @@ using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Scoping;
using Umbraco.Core.Mail;
namespace Umbraco.Core.Services.Implement
{

View File

@@ -70,7 +70,6 @@ namespace Umbraco.Tests.Integration
builder.Services.AddUnique(AppCaches.NoCache);
builder.AddConfiguration()
.AddUmbracoCore()
.AddNuCache()
.Build();
services.AddRouting(); // LinkGenerator

View File

@@ -1,27 +1,17 @@
using System;
using System;
using System.IO;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Services;
using Umbraco.Tests.Integration.Testing;
using Umbraco.Tests.Testing;
using FileSystems = Umbraco.Core.IO.FileSystems;
namespace Umbraco.Tests.IO
{
[TestFixture]
[UmbracoTest()]
[UmbracoTest]
public class FileSystemsTests : UmbracoIntegrationTest
{
[Test]

View File

@@ -23,6 +23,7 @@ using Umbraco.Core.Diagnostics;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Mail;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.PublishedContent;

View File

@@ -39,6 +39,7 @@ using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Mail;
namespace Umbraco.Tests.TestHelpers
{

View File

@@ -18,7 +18,6 @@ using Serilog;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.DependencyInjection;
@@ -28,6 +27,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Logging;
using Umbraco.Core.Mail;
using Umbraco.Core.Manifest;
using Umbraco.Core.Mapping;
using Umbraco.Core.Media;
@@ -383,7 +383,7 @@ namespace Umbraco.Tests.Testing
if (configure == false) return;
Builder
.ComposeCoreMappingProfiles();
.AddCoreMappingProfiles();
}
protected virtual TypeLoader GetTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, IHostingEnvironment hostingEnvironment, ILogger<TypeLoader> logger, IProfilingLogger profilingLogger, UmbracoTestOptions.TypeLoader option)
@@ -452,7 +452,7 @@ namespace Umbraco.Tests.Testing
if (withApplication == false) return;
// default Datalayer/Repositories/SQL/Database/etc...
Builder.ComposeRepositories();
Builder.AddRepositories();
Builder.Services.AddUnique<IExamineManager, ExamineManager>();
@@ -497,7 +497,7 @@ namespace Umbraco.Tests.Testing
=> TestObjects.GetScopeProvider(_loggerFactory, factory.GetService<FileSystems>(), factory.GetService<IUmbracoDatabaseFactory>()));
Builder.Services.AddUnique(factory => (IScopeAccessor)factory.GetRequiredService<IScopeProvider>());
Builder.ComposeServices();
Builder.AddServices();
// composition root is doing weird things, fix
Builder.Services.AddUnique<ITreeService, TreeService>();

View File

@@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Mail;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;

View File

@@ -18,6 +18,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Mail;
using Umbraco.Core.Mapping;
using Umbraco.Core.Media;
using Umbraco.Core.Models;

View File

@@ -1,11 +1,8 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Umbraco.Core.IO;
using Umbraco.Core.Services;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
using Umbraco.Web.Composing;
using Umbraco.Web.Mvc;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
using Constants = Umbraco.Core.Constants;

View File

@@ -105,12 +105,16 @@ namespace Umbraco.Web.Common.DependencyInjection
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddLazySupport();
// Add ASP.NET specific services
builder.Services.AddUnique<IBackOfficeInfo, AspNetCoreBackOfficeInfo>();
builder.Services.AddUnique<IHostingEnvironment, AspNetCoreHostingEnvironment>();
builder.Services.AddHostedService(factory => factory.GetRequiredService<IRuntime>());
// Add supported databases
builder.AddUmbracoSqlCeSupport();
builder.AddUmbracoSqlServerSupport();
// Must be added here because DbProviderFactories is netstandard 2.1 so cannot exist in Infra for now
builder.Services.AddSingleton<IDbProviderFactoryCreator>(factory => new DbProviderFactoryCreator(
DbProviderFactories.GetFactory,
factory.GetServices<ISqlSyntaxProvider>(),
@@ -118,54 +122,6 @@ namespace Umbraco.Web.Common.DependencyInjection
factory.GetServices<IEmbeddedDatabaseCreator>()
));
builder.Services.AddUnique(factory =>
{
var globalSettings = factory.GetRequiredService<IOptions<GlobalSettings>>().Value;
var connectionStrings = factory.GetRequiredService<IOptions<ConnectionStrings>>().Value;
var hostingEnvironment = factory.GetRequiredService<IHostingEnvironment>();
var dbCreator = factory.GetRequiredService<IDbProviderFactoryCreator>();
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var loggerFactory = factory.GetRequiredService<ILoggerFactory>();
return globalSettings.MainDomLock.Equals("SqlMainDomLock") || isWindows == false
? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger<SqlMainDomLock>(), loggerFactory, globalSettings, connectionStrings, dbCreator, hostingEnvironment)
: new MainDomSemaphoreLock(loggerFactory.CreateLogger<MainDomSemaphoreLock>(), hostingEnvironment);
});
builder.Services.AddUnique<IIOHelper>(factory =>
{
var hostingEnvironment = factory.GetRequiredService<IHostingEnvironment>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return new IOHelperLinux(hostingEnvironment);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return new IOHelperOSX(hostingEnvironment);
}
return new IOHelperWindows(hostingEnvironment);
}
);
builder.Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RuntimeCache);
builder.Services.AddUnique(factory => factory.GetRequiredService<AppCaches>().RequestCache);
builder.Services.AddUnique<IProfilingLogger, ProfilingLogger>();
builder.Services.AddUnique<IBackOfficeInfo, AspNetCoreBackOfficeInfo>();
builder.Services.AddUnique<IUmbracoDatabaseFactory, UmbracoDatabaseFactory>();
builder.Services.AddUnique(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().CreateDatabase());
builder.Services.AddUnique(factory => factory.GetRequiredService<IUmbracoDatabaseFactory>().SqlContext);
builder.Services.AddUnique<IUmbracoVersion, UmbracoVersion>();
builder.Services.AddUnique<IRuntimeState, RuntimeState>();
builder.Services.AddUnique<IHostingEnvironment, AspNetCoreHostingEnvironment>();
builder.Services.AddUnique<IMainDom, MainDom>();
builder.Services.AddUnique<IRuntime, CoreRuntime>();
builder.Services.AddHostedService(factory => factory.GetRequiredService<IRuntime>());
builder.AddCoreInitialServices();
builder.AddComposers();

View File

@@ -20,11 +20,11 @@ using Umbraco.Web.Common.Profiler;
using Umbraco.Web.Common.Routing;
using Umbraco.Web.Common.Security;
using Umbraco.Web.Common.Templates;
using Umbraco.Web.Composing.CompositionExtensions;
using Umbraco.Web.Macros;
using Umbraco.Web.Security;
using Umbraco.Web.Templates;
using Umbraco.Web.Common.ModelBinders;
using Umbraco.Infrastructure.DependencyInjection;
namespace Umbraco.Web.Common.Runtime
{
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Common.Runtime
builder.Services.AddUnique<IUmbracoWebsiteSecurityAccessor, HybridUmbracoWebsiteSecurityAccessor>();
//register the install components
builder.ComposeInstaller();
builder.AddInstaller();
var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList();
builder.WithCollectionBuilder<UmbracoApiControllerTypeCollectionBuilder>()