merge release/10.0.0 into v10/dev

commit 9ff06eec6e
Author: Ronald Barendse <ronald@barend.se>
Date:   Wed May 25 11:16:39 2022 +0200

    v10: Instantly reload ConnectionStrings after saving configuration (#12475)

    * Do not replace DataDirectory placeholder when setting connection string

    * Ensure ConnectionStrings options are updated when configuration is reloaded

    * Use CurrentValue to get default Umbraco connection string

commit fcee6dc06a
Author: Paul Johnson <pmj@umbraco.com>
Date:   Wed May 25 10:08:43 2022 +0100

    Fix legacy scope provider no longer implementing ICoreScopeProvider (#12480)

commit 88f3628d0a
Author: Paul Johnson <pmj@umbraco.com>
Date:   Wed May 25 09:49:33 2022 +0100

    Fix options monitor setup for connectionstrings (#12472)

commit 4eeb03e7fb
Author: Johan Runsten <jrunestone@users.noreply.github.com>
Date:   Wed May 25 10:13:25 2022 +0200

    Fixed null check typo in CacheInstructionService. Fixes #12473. (#12474)

    * Fixed null check typo. Fixes #12473.

    * Removed unneccessary null forgiving operator

    Co-authored-by: Johan Runsten <johan.runsten@toxic.se>

commit d810d66e9a
Author: Asbjørn Riis-Knudsen <ar@jf-data.com>
Date:   Tue May 24 17:41:10 2022 +0200

    Fix #12454 by having Coalesce handle null values (#12456)

    * Fix #12454 by having Coalesce handle null values

    * Allow null values in Html.Coalesce #12454

commit 963d4c5051
Author: Paul Johnson <pmj@umbraco.com>
Date:   Tue May 24 13:55:39 2022 +0100

    Ensure unique buildnumber for devops UI
This commit is contained in:
Paul Johnson
2022-05-25 10:48:45 +01:00
parent e6479207f1
commit 8c7905a354
16 changed files with 145 additions and 127 deletions

View File

@@ -97,6 +97,12 @@ stages:
}
dotnet pack --configuration $(buildConfiguration) umbraco.sln -o $(Build.ArtifactStagingDirectory)/nupkg
- script: |
sha="$(Build.SourceVersion)"
sha=${sha:0:7}
buildnumber="$(Build.BuildNumber)_$(Build.BuildId)_$sha"
echo "##vso[build.updatebuildnumber]$buildnumber"
displayName: Update build number
- task: PublishPipelineArtifact@1
displayName: Publish nupkg
inputs:

View File

@@ -7,8 +7,6 @@ namespace Umbraco.Cms.Core.Configuration.Models;
/// </summary>
public class ConnectionStrings // TODO: Rename to [Umbraco]ConnectionString (since v10 this only contains a single connection string)
{
private string? _connectionString;
/// <summary>
/// The default provider name when not present in configuration.
/// </summary>
@@ -39,14 +37,7 @@ public class ConnectionStrings // TODO: Rename to [Umbraco]ConnectionString (sin
/// <value>
/// The connection string.
/// </value>
/// <remarks>
/// When set, the <see cref="DataDirectoryPlaceholder"/> will be replaced with the actual physical path.
/// </remarks>
public string? ConnectionString
{
get => _connectionString;
set => _connectionString = ConfigurationExtensions.ReplaceDataDirectoryPlaceholder(value);
}
public string? ConnectionString { get; set; }
/// <summary>
/// Gets or sets the name of the provider.

View File

@@ -85,7 +85,9 @@ public static partial class UmbracoBuilderExtensions
.AddUmbracoOptions<HelpPageSettings>()
.AddUmbracoOptions<DataTypesSettings>();
// Configure connection string and ensure it's updated when the configuration changes
builder.Services.AddSingleton<IConfigureOptions<ConnectionStrings>, ConfigureConnectionStrings>();
builder.Services.AddSingleton<IOptionsChangeTokenSource<ConnectionStrings>, ConfigurationChangeTokenSource<ConnectionStrings>>();
builder.Services.Configure<InstallDefaultDataSettings>(
Constants.Configuration.NamedOptions.InstallDefaultData.Languages,

View File

@@ -74,7 +74,11 @@ public static class ConfigurationExtensions
if (!string.IsNullOrEmpty(connectionString))
{
// Replace data directory
connectionString = ReplaceDataDirectoryPlaceholder(connectionString);
string? dataDirectory = AppDomain.CurrentDomain.GetData(DataDirectoryName)?.ToString();
if (!string.IsNullOrEmpty(dataDirectory))
{
connectionString = connectionString.Replace(DataDirectoryPlaceholder, dataDirectory);
}
// Get provider name
providerName = configuration.GetConnectionStringProviderName(name);
@@ -86,18 +90,4 @@ public static class ConfigurationExtensions
return connectionString;
}
internal static string? ReplaceDataDirectoryPlaceholder(string? connectionString)
{
if (!string.IsNullOrEmpty(connectionString))
{
string? dataDirectory = AppDomain.CurrentDomain.GetData(DataDirectoryName)?.ToString();
if (!string.IsNullOrEmpty(dataDirectory))
{
return connectionString.Replace(DataDirectoryPlaceholder, dataDirectory);
}
}
return connectionString;
}
}

View File

@@ -1,5 +1,3 @@
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.DependencyInjection;
@@ -14,6 +12,9 @@ namespace Umbraco.Cms.Core.Configuration
{
public class JsonConfigManipulator : IConfigManipulator
{
private const string UmbracoConnectionStringPath = $"ConnectionStrings:{Cms.Core.Constants.System.UmbracoConnectionName}";
private const string UmbracoConnectionStringProviderNamePath = UmbracoConnectionStringPath + ConnectionStrings.ProviderNamePostfix;
private readonly IConfiguration _configuration;
private readonly ILogger<JsonConfigManipulator> _logger;
private readonly object _locker = new object();
@@ -23,18 +24,24 @@ namespace Umbraco.Cms.Core.Configuration
: this(configuration, StaticServiceProvider.Instance.GetRequiredService<ILogger<JsonConfigManipulator>>())
{ }
public JsonConfigManipulator(
IConfiguration configuration,
ILogger<JsonConfigManipulator> logger)
public JsonConfigManipulator(IConfiguration configuration, ILogger<JsonConfigManipulator> logger)
{
_configuration = configuration;
_logger = logger;
}
public string UmbracoConnectionPath { get; } = $"ConnectionStrings:{Cms.Core.Constants.System.UmbracoConnectionName}";
[Obsolete]
public string UmbracoConnectionPath { get; } = UmbracoConnectionStringPath;
public void RemoveConnectionString()
{
var provider = GetJsonConfigurationProvider(UmbracoConnectionPath);
// Update and reload configuration
_configuration[UmbracoConnectionStringPath] = null;
_configuration[UmbracoConnectionStringProviderNamePath] = null;
(_configuration as IConfigurationRoot)?.Reload();
// Remove keys from JSON
var provider = GetJsonConfigurationProvider(UmbracoConnectionStringPath);
var json = GetJson(provider);
if (json is null)
@@ -43,13 +50,20 @@ namespace Umbraco.Cms.Core.Configuration
return;
}
RemoveJsonKey(json, UmbracoConnectionPath);
RemoveJsonKey(json, UmbracoConnectionStringPath);
RemoveJsonKey(json, UmbracoConnectionStringProviderNamePath);
SaveJson(provider, json);
}
public void SaveConnectionString(string connectionString, string? providerName)
{
// Update and reload configuration
_configuration[UmbracoConnectionStringPath] = connectionString;
_configuration[UmbracoConnectionStringProviderNamePath] = providerName;
(_configuration as IConfigurationRoot)?.Reload();
// Save keys to JSON
var provider = GetJsonConfigurationProvider();
var json = GetJson(provider);
@@ -60,18 +74,21 @@ namespace Umbraco.Cms.Core.Configuration
}
var item = GetConnectionItem(connectionString, providerName);
if (item is not null)
{
json?.Merge(item, new JsonMergeSettings());
json.Merge(item, new JsonMergeSettings());
}
SaveJson(provider, json);
}
public void SaveConfigValue(string key, object value)
{
// Update and reload configuration
_configuration[key] = value?.ToString();
(_configuration as IConfigurationRoot)?.Reload();
// Save key to JSON
var provider = GetJsonConfigurationProvider();
var json = GetJson(provider);
@@ -101,11 +118,15 @@ namespace Umbraco.Cms.Core.Configuration
}
SaveJson(provider, json);
}
public void SaveDisableRedirectUrlTracking(bool disable)
{
// Update and reload configuration
_configuration["Umbraco:CMS:WebRouting:DisableRedirectUrlTracking"] = disable.ToString();
(_configuration as IConfigurationRoot)?.Reload();
// Save key to JSON
var provider = GetJsonConfigurationProvider();
var json = GetJson(provider);
@@ -116,10 +137,9 @@ namespace Umbraco.Cms.Core.Configuration
}
var item = GetDisableRedirectUrlItem(disable);
if (item is not null)
{
json?.Merge(item, new JsonMergeSettings());
json.Merge(item, new JsonMergeSettings());
}
SaveJson(provider, json);
@@ -127,6 +147,11 @@ namespace Umbraco.Cms.Core.Configuration
public void SetGlobalId(string id)
{
// Update and reload configuration
_configuration["Umbraco:CMS:Global:Id"] = id;
(_configuration as IConfigurationRoot)?.Reload();
// Save key to JSON
var provider = GetJsonConfigurationProvider();
var json = GetJson(provider);
@@ -137,10 +162,9 @@ namespace Umbraco.Cms.Core.Configuration
}
var item = GetGlobalIdItem(id);
if (item is not null)
{
json?.Merge(item, new JsonMergeSettings());
json.Merge(item, new JsonMergeSettings());
}
SaveJson(provider, json);
@@ -197,8 +221,13 @@ namespace Umbraco.Cms.Core.Configuration
writer.WriteStartObject();
writer.WritePropertyName(Constants.System.UmbracoConnectionName);
writer.WriteValue(connectionString);
writer.WritePropertyName($"{Constants.System.UmbracoConnectionName}{ConnectionStrings.ProviderNamePostfix}");
writer.WriteValue(providerName);
if (!string.IsNullOrEmpty(providerName))
{
writer.WritePropertyName(Constants.System.UmbracoConnectionName + ConnectionStrings.ProviderNamePostfix);
writer.WriteValue(providerName);
}
writer.WriteEndObject();
writer.WriteEndObject();
@@ -216,8 +245,13 @@ namespace Umbraco.Cms.Core.Configuration
token?.Parent?.Remove();
}
private void SaveJson(JsonConfigurationProvider provider, JObject? json)
private void SaveJson(JsonConfigurationProvider? provider, JObject? json)
{
if (provider is null)
{
return;
}
lock (_locker)
{
if (provider.Source.FileProvider is PhysicalFileProvider physicalFileProvider)
@@ -243,8 +277,13 @@ namespace Umbraco.Cms.Core.Configuration
}
}
private JObject? GetJson(JsonConfigurationProvider provider)
private JObject? GetJson(JsonConfigurationProvider? provider)
{
if (provider is null)
{
return null;
}
lock (_locker)
{
if (provider.Source.FileProvider is not PhysicalFileProvider physicalFileProvider)
@@ -269,22 +308,21 @@ namespace Umbraco.Cms.Core.Configuration
}
}
private JsonConfigurationProvider GetJsonConfigurationProvider(string? requiredKey = null)
private JsonConfigurationProvider? GetJsonConfigurationProvider(string? requiredKey = null)
{
if (_configuration is IConfigurationRoot configurationRoot)
{
foreach (var provider in configurationRoot.Providers)
{
if (provider is JsonConfigurationProvider jsonConfigurationProvider)
if (provider is JsonConfigurationProvider jsonConfigurationProvider &&
(requiredKey is null || provider.TryGet(requiredKey, out _)))
{
if (requiredKey is null || provider.TryGet(requiredKey, out _))
{
return jsonConfigurationProvider;
}
return jsonConfigurationProvider;
}
}
}
throw new InvalidOperationException("Could not find a writable json config source");
return null;
}
/// <summary>

View File

@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
@@ -28,7 +26,8 @@ namespace Umbraco.Cms.Infrastructure.Install
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
private InstallationType? _installationType;
public InstallHelper(DatabaseBuilder databaseBuilder,
public InstallHelper(
DatabaseBuilder databaseBuilder,
ILogger<InstallHelper> logger,
IUmbracoVersion umbracoVersion,
IOptionsMonitor<ConnectionStrings> connectionStrings,
@@ -75,10 +74,17 @@ namespace Umbraco.Cms.Infrastructure.Install
dbProvider = _umbracoDatabaseFactory.SqlContext.SqlSyntax.DbProvider;
}
var installLog = new InstallLog(installId: installId, isUpgrade: IsBrandNewInstall == false,
installCompleted: isCompleted, timestamp: DateTime.Now, versionMajor: _umbracoVersion.Version.Major,
versionMinor: _umbracoVersion.Version.Minor, versionPatch: _umbracoVersion.Version.Build,
versionComment: _umbracoVersion.Comment, error: errorMsg, userAgent: userAgent,
var installLog = new InstallLog(
installId: installId,
isUpgrade: IsBrandNewInstall == false,
installCompleted: isCompleted,
timestamp: DateTime.Now,
versionMajor: _umbracoVersion.Version.Major,
versionMinor: _umbracoVersion.Version.Minor,
versionPatch: _umbracoVersion.Version.Build,
versionComment: _umbracoVersion.Comment,
error: errorMsg,
userAgent: userAgent,
dbProvider: dbProvider);
await _installationService.LogInstall(installLog);
@@ -96,7 +102,7 @@ namespace Umbraco.Cms.Infrastructure.Install
/// <c>true</c> if this is a brand new install; otherwise, <c>false</c>.
/// </value>
private bool IsBrandNewInstall =>
_connectionStrings.Get(Constants.System.UmbracoConnectionName).IsConnectionStringConfigured() == false ||
_connectionStrings.CurrentValue.IsConnectionStringConfigured() == false ||
_databaseBuilder.IsDatabaseConfigured == false ||
_databaseBuilder.CanConnectToDatabase == false ||
_databaseBuilder.IsUmbracoInstalled() == false;

View File

@@ -50,9 +50,8 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
private bool ShouldDisplayView()
{
// If the connection string is already present in web.config we don't need to show the settings page and we jump to installing/upgrading.
var databaseSettings = _connectionStrings.Get(Core.Constants.System.UmbracoConnectionName);
if (databaseSettings.IsConnectionStringConfigured())
// If the connection string is already present in config we don't need to show the settings page and we jump to installing/upgrading.
if (_connectionStrings.CurrentValue.IsConnectionStringConfigured())
{
try
{

View File

@@ -1,6 +1,3 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
@@ -16,8 +13,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
{
[InstallSetupStep(InstallationType.Upgrade | InstallationType.NewInstall,
"DatabaseUpgrade", 12, "")]
[InstallSetupStep(InstallationType.Upgrade | InstallationType.NewInstall, "DatabaseUpgrade", 12, "")]
public class DatabaseUpgradeStep : InstallSetupStep<object>
{
private readonly DatabaseBuilder _databaseBuilder;
@@ -66,28 +62,28 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
public override bool RequiresExecution(object model)
{
//if it's properly configured (i.e. the versions match) then no upgrade necessary
// If it's properly configured (i.e. the versions match) then no upgrade necessary
if (_runtime.Level == RuntimeLevel.Run)
{
return false;
}
// This step relies on the previous one completed - because it has stored some information we need
var installSteps = InstallStatusTracker.GetStatus().ToArray();
//this step relies on the previous one completed - because it has stored some information we need
if (installSteps.Any(x => x.Name == "DatabaseInstall" && x.AdditionalData.ContainsKey("upgrade")) == false)
{
return false;
}
var databaseSettings = _connectionStrings.Get(Core.Constants.System.UmbracoConnectionName);
if (databaseSettings.IsConnectionStringConfigured())
if (_connectionStrings.CurrentValue.IsConnectionStringConfigured())
{
// a connection string was present, determine whether this is an install/upgrade
// return true (upgrade) if there is an installed version, else false (install)
// A connection string was present, determine whether this is an install/upgrade
// Return true (upgrade) if there is an installed version, else false (install)
var result = _databaseBuilder.ValidateSchema();
return result?.DetermineHasInstalledVersion() ?? false;
}
//no connection string configured, probably a fresh install
// No connection string configured, probably a fresh install
return false;
}
}

View File

@@ -176,17 +176,11 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
}
}
public override string View
{
get
{
return ShowView()
// the user UI
? "user"
// continue install UI
: "continueinstall";
}
}
public override string View => ShowView()
// the user UI
? "user"
// continue install UI
: "continueinstall";
private string GetTelemetryLevelDescription(TelemetryLevel telemetryLevel) => telemetryLevel switch
{
@@ -200,40 +194,34 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
{
var installState = InstallState.Unknown;
// TODO: we need to do a null check here since this could be entirely missing and we end up with a null ref
// exception in the installer.
var databaseSettings = _connectionStrings.Get(Constants.System.UmbracoConnectionName);
var hasConnString = databaseSettings != null && _databaseBuilder.IsDatabaseConfigured;
if (hasConnString)
if (_databaseBuilder.IsDatabaseConfigured)
{
installState = (installState | InstallState.HasConnectionString) & ~InstallState.Unknown;
}
var connStringConfigured = databaseSettings?.IsConnectionStringConfigured() ?? false;
if (connStringConfigured)
var umbracoConnectionString = _connectionStrings.CurrentValue;
var isConnectionStringConfigured = umbracoConnectionString.IsConnectionStringConfigured();
if (isConnectionStringConfigured)
{
installState = (installState | InstallState.ConnectionStringConfigured) & ~InstallState.Unknown;
}
var factory = _dbProviderFactoryCreator.CreateFactory(databaseSettings?.ProviderName);
var canConnect = connStringConfigured && DbConnectionExtensions.IsConnectionAvailable(databaseSettings?.ConnectionString, factory);
if (canConnect)
var factory = _dbProviderFactoryCreator.CreateFactory(umbracoConnectionString.ProviderName);
var isConnectionAvailable = isConnectionStringConfigured && DbConnectionExtensions.IsConnectionAvailable(umbracoConnectionString.ConnectionString, factory);
if (isConnectionAvailable)
{
installState = (installState | InstallState.CanConnect) & ~InstallState.Unknown;
}
var umbracoInstalled = canConnect ? _databaseBuilder.IsUmbracoInstalled() : false;
if (umbracoInstalled)
var isUmbracoInstalled = isConnectionAvailable && _databaseBuilder.IsUmbracoInstalled();
if (isUmbracoInstalled)
{
installState = (installState | InstallState.UmbracoInstalled) & ~InstallState.Unknown;
}
var hasNonDefaultUser = umbracoInstalled ? _databaseBuilder.HasSomeNonDefaultUser() : false;
if (hasNonDefaultUser)
var hasSomeNonDefaultUser = isUmbracoInstalled && _databaseBuilder.HasSomeNonDefaultUser();
if (hasSomeNonDefaultUser)
{
installState = (installState | InstallState.HasNonDefaultUser) & ~InstallState.Unknown;
}
@@ -245,14 +233,12 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
{
var installState = GetInstallState();
return installState.HasFlag(InstallState.Unknown)
|| !installState.HasFlag(InstallState.UmbracoInstalled);
return installState.HasFlag(InstallState.Unknown) || !installState.HasFlag(InstallState.UmbracoInstalled);
}
public override bool RequiresExecution(UserModel model)
{
var installState = GetInstallState();
if (installState.HasFlag(InstallState.Unknown))
{
// In this one case when it's a brand new install and nothing has been configured, make sure the
@@ -260,8 +246,7 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
_cookieManager.ExpireCookie(_securitySettings.AuthCookieName);
}
return installState.HasFlag(InstallState.Unknown)
|| !installState.HasFlag(InstallState.HasNonDefaultUser);
return installState.HasFlag(InstallState.Unknown) || !installState.HasFlag(InstallState.HasNonDefaultUser);
}
[Flags]

View File

@@ -155,28 +155,24 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install
var connectionString = providerMeta.GenerateConnectionString(databaseSettings);
var providerName = databaseSettings.ProviderName ?? providerMeta.ProviderName;
if (providerMeta.RequiresConnectionTest && !CanConnect(connectionString, providerName!))
if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(providerName) ||
(providerMeta.RequiresConnectionTest && !CanConnect(connectionString, providerName)))
{
return false;
}
if (!isTrialRun)
{
_configManipulator.SaveConnectionString(connectionString!, providerName);
Configure(connectionString!, providerName, _globalSettings.CurrentValue.InstallMissingDatabase || providerMeta.ForceCreateDatabase);
_configManipulator.SaveConnectionString(connectionString, providerName);
Configure(_globalSettings.CurrentValue.InstallMissingDatabase || providerMeta.ForceCreateDatabase);
}
return true;
}
private void Configure(string connectionString, string? providerName, bool installMissingDatabase)
private void Configure(bool installMissingDatabase)
{
// Update existing connection string
var umbracoConnectionString = _connectionStrings.Get(Core.Constants.System.UmbracoConnectionName);
umbracoConnectionString.ConnectionString = connectionString;
umbracoConnectionString.ProviderName = providerName;
_databaseFactory.Configure(umbracoConnectionString);
_databaseFactory.Configure(_connectionStrings.CurrentValue);
if (installMissingDatabase)
{

View File

@@ -97,7 +97,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_loggerFactory = loggerFactory;
ConnectionStrings umbracoConnectionString = connectionStrings.Get(Constants.System.UmbracoConnectionName);
ConnectionStrings umbracoConnectionString = connectionStrings.CurrentValue;
if (!umbracoConnectionString.IsConnectionStringConfigured())
{
logger.LogDebug("Missing connection string, defer configuration.");

View File

@@ -6,7 +6,7 @@ using Umbraco.Cms.Infrastructure.Persistence;
namespace Umbraco.Cms.Core.Scoping;
[Obsolete("Please use Umbraco.Cms.Infrastructure.Scoping.IScopeProvider or Umbraco.Cms.Core.Scoping.ICoreScopeProvider instead.")]
public interface IScopeProvider
public interface IScopeProvider : ICoreScopeProvider
{
/// <summary>
/// Creates an ambient scope.

View File

@@ -314,12 +314,12 @@ namespace Umbraco.Cms
private static List<RefreshInstruction> GetAllInstructions(IEnumerable<JToken>? jsonInstructions)
{
var result = new List<RefreshInstruction>();
if (jsonInstructions is not null)
if (jsonInstructions is null)
{
return result;
}
foreach (JToken jsonItem in jsonInstructions!)
foreach (JToken jsonItem in jsonInstructions)
{
// Could be a JObject in which case we can convert to a RefreshInstruction.
// Otherwise it could be another JArray - in which case we'll iterate that.

View File

@@ -89,10 +89,10 @@ public sealed class HtmlStringUtilities
return sb.ToString();
}
public string Coalesce(params object[] args)
public string Coalesce(params object?[] args)
{
var arg = args
.Select(x => x.ToString())
.Select(x => x?.ToString())
.FirstOrDefault(x => string.IsNullOrWhiteSpace(x) == false);
return arg ?? string.Empty;

View File

@@ -910,7 +910,7 @@ public static class HtmlHelperRenderExtensions
/// <summary>
/// Will take the first non-null value in the collection and return the value of it.
/// </summary>
public static string Coalesce(this IHtmlHelper helper, params object[] args)
public static string Coalesce(this IHtmlHelper helper, params object?[] args)
=> s_stringUtilities.Coalesce(args);
/// <summary>

View File

@@ -1,4 +1,5 @@
using NUnit.Framework;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Tests.Common.Testing;
using Umbraco.Cms.Tests.Integration.Testing;
@@ -18,4 +19,12 @@ public class LegacyScopeProviderTests : UmbracoIntegrationTest
Assert.IsInstanceOf<global::Umbraco.Cms.Core.Scoping.IScope>(scope);
}
}
[Test]
public void LegacyScopeProvider_Always_IsACoreScopeProvider()
{
var scopeProvider = GetRequiredService<global::Umbraco.Cms.Core.Scoping.IScopeProvider>();
Assert.IsInstanceOf<ICoreScopeProvider>(scopeProvider);
}
}