Merge remote-tracking branch 'origin/netcore/dev' into netcore/feature/ab5820-webprofiler-aspnetcore

# Conflicts:
#	src/Umbraco.Web.UI.NetCore/Startup.cs
This commit is contained in:
Bjarke Berg
2020-03-24 19:38:44 +01:00
42 changed files with 910 additions and 250 deletions

View File

@@ -84,9 +84,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore
}
}
// TODO: This may need to take into account ~/ paths which means the ApplicationVirtualPath and is this the content root or web root?
public string MapPath(string path) => Path.Combine(_webHostEnvironment.WebRootPath, path);
// TODO: Need to take into account 'root' here
public string ToAbsolute(string virtualPath, string root)
{
if (Uri.TryCreate(virtualPath, UriKind.Absolute, out _))

View File

@@ -3,7 +3,7 @@ using Umbraco.Net;
namespace Umbraco.Web.BackOffice.AspNetCore
{
internal class AspNetIpResolver : IIpResolver
public class AspNetIpResolver : IIpResolver
{
private readonly IHttpContextAccessor _httpContextAccessor;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Umbraco.Net;
namespace Umbraco.Web.BackOffice.AspNetCore
@@ -12,6 +13,18 @@ namespace Umbraco.Web.BackOffice.AspNetCore
_httpContextAccessor = httpContextAccessor;
}
public string SessionId => _httpContextAccessor?.HttpContext.Session?.Id;
public string SessionId
{
get
{
var httpContext = _httpContextAccessor?.HttpContext;
// If session isn't enabled this will throw an exception so we check
var sessionFeature = httpContext?.Features.Get<ISessionFeature>();
return sessionFeature != null
? httpContext?.Session?.Id
: "0";
}
}
}
}

View File

@@ -1,3 +1,6 @@
using System;
using System.Data.Common;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
@@ -7,20 +10,29 @@ using Umbraco.Composing;
using Umbraco.Configuration;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.BackOffice.AspNetCore
{
public static class UmbracoBackOfficeServiceCollectionExtensions
{
public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
var configuration = serviceProvider.GetService<IConfiguration>();
if (configuration == null)
throw new InvalidOperationException($"Could not resolve {typeof(IConfiguration)} from the container");
var configsFactory = new AspNetCoreConfigsFactory(configuration);
var configs = configsFactory.Create();
@@ -30,44 +42,102 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return services;
}
public static IServiceCollection AddUmbracoBackOffice(this IServiceCollection services)
/// <summary>
/// Adds the Umbraco Back Core requirements
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
/// <remarks>
/// Must be called after all services are added to the application because we are cross-wiring the container (currently)
/// </remarks>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services)
{
if (!UmbracoServiceProviderFactory.IsActive)
throw new InvalidOperationException("Ensure to add UseUmbraco() in your Program.cs after ConfigureWebHostDefaults to enable Umbraco's service provider factory");
var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer;
return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly());
}
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var serviceProvider = services.BuildServiceProvider();
CreateCompositionRoot(services);
var httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();
var webHostEnvironment = serviceProvider.GetService<IWebHostEnvironment>();
var hostApplicationLifetime = serviceProvider.GetService<IHostApplicationLifetime>();
// TODO: Get rid of this 'Current' requirement
var globalSettings = Current.Configs.Global();
var umbracoVersion = new UmbracoVersion(globalSettings);
var configs = serviceProvider.GetService<Configs>();
// TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however
// this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now.
var typeFinder = new TypeFinder(Current.Logger, new DefaultUmbracoAssemblyProvider(entryAssembly));
services.CreateCompositionRoot(
httpContextAccessor,
webHostEnvironment,
hostApplicationLifetime,
configs);
var coreRuntime = GetCoreRuntime(
Current.Configs,
umbracoVersion,
Current.IOHelper,
Current.Logger,
Current.Profiler,
Current.HostingEnvironment,
Current.BackOfficeInfo,
typeFinder);
var factory = coreRuntime.Boot(umbContainer);
return services;
}
public static IServiceCollection CreateCompositionRoot(
this IServiceCollection services,
IHttpContextAccessor httpContextAccessor,
IWebHostEnvironment webHostEnvironment,
IHostApplicationLifetime hostApplicationLifetime,
Configs configs)
private static IRuntime GetCoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger,
IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo,
ITypeFinder typeFinder)
{
var connectionStringConfig = configs.ConnectionStrings()[Constants.System.UmbracoConnectionName];
var dbProviderFactoryCreator = new SqlServerDbProviderFactoryCreator(
connectionStringConfig?.ProviderName,
DbProviderFactories.GetFactory);
// Determine if we should use the sql main dom or the default
var globalSettings = configs.Global();
var connStrings = configs.ConnectionStrings();
var appSettingMainDomLock = globalSettings.MainDomLock;
var mainDomLock = appSettingMainDomLock == "SqlMainDomLock"
? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connStrings, dbProviderFactoryCreator)
: new MainDomSemaphoreLock(logger, hostingEnvironment);
var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetCoreBootPermissionsChecker(),
hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder);
return coreRuntime;
}
private static void CreateCompositionRoot(IServiceCollection services)
{
// TODO: This isn't the best to have to resolve the services now but to avoid this will
// require quite a lot of re-work.
var serviceProvider = services.BuildServiceProvider();
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
var webHostEnvironment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
var hostApplicationLifetime = serviceProvider.GetRequiredService<IHostApplicationLifetime>();
var configs = serviceProvider.GetService<Configs>();
if (configs == null)
throw new InvalidOperationException($"Could not resolve type {typeof(Configs)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}");
var hostingSettings = configs.Hosting();
var coreDebug = configs.CoreDebug();
var globalSettings = configs.Global();
var hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment,
httpContextAccessor, hostApplicationLifetime);
var hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime);
var ioHelper = new IOHelper(hostingEnvironment, globalSettings);
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment,
new AspNetCoreSessionIdResolver(httpContextAccessor),
// need to build a new service provider since the one already resolved above doesn't have the IRequestCache yet
() => services.BuildServiceProvider().GetService<IRequestCache>(), coreDebug, ioHelper,
new AspNetCoreMarchal());
@@ -75,8 +145,14 @@ namespace Umbraco.Web.BackOffice.AspNetCore
var profiler = new LogProfiler(logger);
Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler);
}
return services;
private class AspNetCoreBootPermissionsChecker : IUmbracoBootPermissionChecker
{
public void ThrowIfNotPermissions()
{
// nothing to check
}
}
}
}