Merge pull request #8095 from umbraco/netcore/feature/redirect-installer

Redirect to installer and ext method/startup cleanup
This commit is contained in:
Bjarke Berg
2020-05-12 10:58:49 +02:00
committed by GitHub
24 changed files with 287 additions and 250 deletions

View File

@@ -49,6 +49,11 @@
/// The default authentication type used for remembering that 2FA is not needed on next login
/// </summary>
public const string TwoFactorRememberBrowserCookie = "TwoFactorRememberBrowser";
public static class Mvc
{
public const string InstallArea = "UmbracoInstall";
}
}
}
}

View File

@@ -117,7 +117,7 @@ namespace Umbraco.Core
.TrimStart("/");
//check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(hostingEnvironment.ToAbsolute("~/install").TrimStart("/"));
return afterAuthority.InvariantStartsWith(hostingEnvironment.ToAbsolute(Constants.SystemDirectories.Install).TrimStart("/"));
}
/// <summary>

View File

@@ -1,9 +1,11 @@
using LightInject;
using LightInject.Microsoft.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using Umbraco.Composing;
using Umbraco.Core.Composing.LightInject;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Core.Composing
{
@@ -12,9 +14,10 @@ namespace Umbraco.Core.Composing
/// </summary>
public class UmbracoServiceProviderFactory : IServiceProviderFactory<IServiceContainer>
{
public UmbracoServiceProviderFactory(ServiceContainer container)
public UmbracoServiceProviderFactory(ServiceContainer container, bool initializeCurrent)
{
_container = new LightInjectContainer(container);
_initializeCurrent = initializeCurrent;
}
/// <summary>
@@ -35,6 +38,7 @@ namespace Umbraco.Core.Composing
var container = CreateServiceContainer();
UmbracoContainer = _container = new LightInjectContainer(container);
IsActive = true;
_initializeCurrent = true;
}
// see here for orig lightinject version https://github.com/seesharper/LightInject.Microsoft.DependencyInjection/blob/412566e3f70625e6b96471db5e1f7cd9e3e1eb18/src/LightInject.Microsoft.DependencyInjection/LightInject.Microsoft.DependencyInjection.cs#L263
@@ -43,6 +47,7 @@ namespace Umbraco.Core.Composing
IServiceCollection _services;
readonly LightInjectContainer _container;
private readonly bool _initializeCurrent;
internal LightInjectContainer GetContainer() => _container;
@@ -75,6 +80,20 @@ namespace Umbraco.Core.Composing
public IServiceProvider CreateServiceProvider(IServiceContainer containerBuilder)
{
var provider = containerBuilder.CreateServiceProvider(_services);
if (_initializeCurrent)
{
// after cross wiring, configure "Current"
Current.Initialize(
_container.GetInstance<Umbraco.Core.Logging.ILogger>(),
_container.GetInstance<Configs>(),
_container.GetInstance<IIOHelper>(),
_container.GetInstance<Umbraco.Core.Hosting.IHostingEnvironment>(),
_container.GetInstance<IBackOfficeInfo>(),
_container.GetInstance<Umbraco.Core.Logging.IProfiler>());
}
return provider;
}

View File

@@ -31,7 +31,7 @@ namespace Umbraco.Tests.Integration
// LightInject / Umbraco
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
var serviceProviderFactory = new UmbracoServiceProviderFactory(container);
var serviceProviderFactory = new UmbracoServiceProviderFactory(container, false);
var umbracoContainer = serviceProviderFactory.GetContainer();
serviceProviderFactory.CreateBuilder(services); // called during Host Builder, needed to capture services

View File

@@ -15,7 +15,6 @@ using Umbraco.Tests.Common;
using Umbraco.Tests.Integration.Extensions;
using Umbraco.Tests.Integration.Implementations;
using Umbraco.Tests.Integration.Testing;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Extensions;
@@ -47,7 +46,7 @@ namespace Umbraco.Tests.Integration
{
// LightInject / Umbraco
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
var serviceProviderFactory = new UmbracoServiceProviderFactory(container);
var serviceProviderFactory = new UmbracoServiceProviderFactory(container, false);
var umbracoContainer = serviceProviderFactory.GetContainer();
// Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container

View File

@@ -17,7 +17,6 @@ using Umbraco.Core.Strings;
using Umbraco.Tests.Common.Builders;
using Umbraco.Tests.Integration.Extensions;
using Umbraco.Tests.Integration.Implementations;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Extensions;
namespace Umbraco.Tests.Integration.Testing
@@ -35,7 +34,7 @@ namespace Umbraco.Tests.Integration.Testing
public static LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
{
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
serviceProviderFactory = new UmbracoServiceProviderFactory(container);
serviceProviderFactory = new UmbracoServiceProviderFactory(container, false);
var umbracoContainer = serviceProviderFactory.GetContainer();
return umbracoContainer;
}

View File

@@ -1,16 +0,0 @@
using Microsoft.AspNetCore.Http;
namespace Umbraco.Web.BackOffice.AspNetCore
{
internal class AspNetCoreHttpContextAccessor //: IHttpContextAccessor
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AspNetCoreHttpContextAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public HttpContext HttpContext => _httpContextAccessor.HttpContext;
}
}

View File

@@ -1,111 +0,0 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Context;
using Smidge;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Extensions;
using Umbraco.Infrastructure.Logging.Serilog.Enrichers;
using Umbraco.Web.Common.Middleware;
namespace Umbraco.Web.BackOffice.AspNetCore
{
public static class UmbracoApplicationBuilderExtensions
{
public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
// TODO: start the back office
return app;
}
/// <summary>
/// Start Umbraco
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (app.UmbracoCanBoot())
{
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
// Register our global threadabort enricher for logging
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
// Start the runtime!
runtime.Start();
}
else
{
// TODO: Register simple middleware to show the error like we used to in UmbracoModule? Or maybe that's part of a UseUmbracoWebsite/backoffice type thing .. probably :)
}
return app;
}
/// <summary>
/// Ensures the runtime is shutdown when the application is shutting down
/// </summary>
private class CoreRuntimeShutdown : IRegisteredObject
{
public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime)
{
_runtime = runtime;
_hostLifetime = hostLifetime;
}
private bool _completed = false;
private readonly IRuntime _runtime;
private readonly IApplicationShutdownRegistry _hostLifetime;
public void Stop(bool immediate)
{
if (!_completed)
{
_completed = true;
_runtime.Terminate();
_hostLifetime.UnregisterObject(this);
}
}
}
public static IApplicationBuilder UseUmbracoRequestLogging(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
app.UseMiddleware<UmbracoRequestLoggingMiddleware>();
return app;
}
public static IApplicationBuilder UseUmbracoRuntimeMinification(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
app.UseSmidge();
return app;
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using Microsoft.AspNetCore.Builder;
using SixLabors.ImageSharp.Web.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Extensions
{
public static class UmbracoBackOfficeApplicationBuilderExtensions
{
public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
app.UseEndpoints(endpoints =>
{
// TODO: This is temporary, 'umbraco' cannot be hard coded, needs to use GetUmbracoMvcArea()
// but actually we need to route all back office stuff in a back office area like we do in v8
// TODO: We will also need to detect runtime state here and redirect to the installer,
// Potentially switch this to dynamic routing so we can essentially disable/overwrite the back office routes to redirect to install
// when required, example https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/
endpoints.MapControllerRoute("Backoffice", "/umbraco/{Action}", new
{
Controller = "BackOffice",
Action = "Default"
});
});
app.UseUmbracoRuntimeMinification();
// 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 UseUmbracoWebsite too?
app.UseImageSharp();
app.UseStaticFiles();
return app;
}
}
}

View File

@@ -1,12 +1,18 @@
using System;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Context;
using Smidge;
using StackExchange.Profiling;
using Umbraco.Core;
using Umbraco.Core.Hosting;
using Umbraco.Infrastructure.Logging.Serilog.Enrichers;
using Umbraco.Web.Common.Middleware;
namespace Umbraco.Extensions
{
public static class ApplicationBuilderExtensions
{
/// <summary>
@@ -21,6 +27,42 @@ namespace Umbraco.Extensions
return runtime.State.Level > RuntimeLevel.BootFailed;
}
/// <summary>
/// Start Umbraco
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (app.UmbracoCanBoot())
{
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
// Register our global threadabort enricher for logging
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
// Start the runtime!
runtime.Start();
}
else
{
// TODO: Register simple middleware to show the error like we used to in UmbracoModule? Or maybe that's part of a UseUmbracoWebsite/backoffice type thing .. probably :)
}
return app;
}
/// <summary>
/// Enables middlewares required to run Umbraco
/// </summary>
@@ -37,6 +79,60 @@ namespace Umbraco.Extensions
app.UseMiddleware<MiniProfilerMiddleware>();
return app;
}
public static IApplicationBuilder UseUmbracoRequestLogging(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
app.UseMiddleware<UmbracoRequestLoggingMiddleware>();
return app;
}
/// <summary>
/// Enables runtime minification for Umbraco
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoRuntimeMinification(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (!app.UmbracoCanBoot()) return app;
app.UseSmidge();
return app;
}
/// <summary>
/// Ensures the runtime is shutdown when the application is shutting down
/// </summary>
private class CoreRuntimeShutdown : IRegisteredObject
{
public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime)
{
_runtime = runtime;
_hostLifetime = hostLifetime;
}
private bool _completed = false;
private readonly IRuntime _runtime;
private readonly IApplicationShutdownRegistry _hostLifetime;
public void Stop(bool immediate)
{
if (!_completed)
{
_completed = true;
_runtime.Terminate();
_hostLifetime.UnregisterObject(this);
}
}
}
}
}

View File

@@ -6,6 +6,7 @@ using Umbraco.Core;
using Umbraco.Web.Common.Controllers;
using Umbraco.Extensions;
using Umbraco.Web.WebApi;
using Microsoft.AspNetCore.Mvc.Routing;
namespace Umbraco.Extensions
{
@@ -101,30 +102,26 @@ namespace Umbraco.Extensions
if (controllerName == null) throw new ArgumentNullException(nameof(controllerName));
if (string.IsNullOrWhiteSpace(controllerName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(controllerName));
string routeName;
if (area.IsNullOrWhiteSpace())
{
routeName = string.Format("umbraco-{0}-{1}", "api", controllerName);
if (id == null)
{
return url.RouteUrl(routeName, new { controller = controllerName, action = actionName, httproute = "" });
return url.Action(actionName, controllerName);
}
else
{
return url.RouteUrl(routeName, new { controller = controllerName, action = actionName, id = id, httproute = "" });
return url.Action(actionName, controllerName, new { id = id });
}
}
else
{
routeName = string.Format("umbraco-{0}-{1}-{2}", "api", area, controllerName);
if (id == null)
{
return url.RouteUrl(routeName, new { controller = controllerName, action = actionName, httproute = "" });
return url.Action(actionName, controllerName, new { area = area });
}
else
{
return url.RouteUrl(routeName, new { controller = controllerName, action = actionName, id = id, httproute = "" });
return url.Action(actionName, controllerName, new { area = area, id = id });
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web;
namespace Umbraco.Extensions
{
public static class UmbracoInstallApplicationBuilderExtensions
{
/// <summary>
/// Enables the Umbraco installer
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoInstaller(this IApplicationBuilder app)
{
app.UseEndpoints(endpoints =>
{
var runtime = app.ApplicationServices.GetRequiredService<IRuntimeState>();
var logger = app.ApplicationServices.GetRequiredService<ILogger>();
var uriUtility = app.ApplicationServices.GetRequiredService<UriUtility>();
switch (runtime.Level)
{
case RuntimeLevel.Install:
case RuntimeLevel.Upgrade:
var installPath = uriUtility.ToAbsolute(Constants.SystemDirectories.Install).EnsureEndsWith('/');
endpoints.MapAreaControllerRoute(
"umbraco-install-api",
Umbraco.Core.Constants.Web.Mvc.InstallArea,
$"{installPath}api/{{Action}}",
new { controller = "InstallApi" });
endpoints.MapAreaControllerRoute(
"umbraco-install",
Umbraco.Core.Constants.Web.Mvc.InstallArea,
$"{installPath}{{controller}}/{{Action}}",
new { controller = "Install", action = "Index" });
// TODO: Potentially switch this to dynamic routing so we can essentially disable/overwrite the back office routes to redirect to install,
// example https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/
// register catch all because if we are in install/upgrade mode then we'll catch everything and redirect
endpoints.MapGet("{*url}", context =>
{
var uri = context.Request.GetEncodedUrl();
// redirect to install
ReportRuntime(logger, runtime.Level, "Umbraco must install or upgrade.");
var installUrl = $"{installPath}?redir=true&url={uri}";
context.Response.Redirect(installUrl, false);
return Task.CompletedTask;
});
break;
}
});
return app;
}
private static bool _reported;
private static RuntimeLevel _reportedLevel;
private static void ReportRuntime(ILogger logger, RuntimeLevel level, string message)
{
if (_reported && _reportedLevel == level) return;
_reported = true;
_reportedLevel = level;
logger.Warn(typeof(UmbracoInstallApplicationBuilderExtensions), message);
}
}
}

View File

@@ -20,6 +20,7 @@ using Smidge.Nuglify;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Web.Common.ApplicationModels;
using Umbraco.Web.Common.Middleware;
using Umbraco.Web.Common.ModelBinding;
namespace Umbraco.Extensions
@@ -33,6 +34,9 @@ namespace Umbraco.Extensions
/// <returns></returns>
public static IServiceCollection AddUmbracoWebComponents(this IServiceCollection services)
{
services.AddTransient<UmbracoRequestLoggingMiddleware>();
services.AddTransient<UmbracoRequestMiddleware>();
services.TryAddSingleton<UmbracoJsonModelBinder>();
services.ConfigureOptions<UmbracoMvcConfigureOptions>();
services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, UmbracoApiBehaviorApplicationModelProvider>());

View File

@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Semver;
namespace Umbraco.Web
namespace Umbraco.Extensions
{
public static class ViewDataExtensions
{

View File

@@ -24,7 +24,7 @@ namespace Umbraco.Web.Common.Install
[TypeFilter(typeof(HttpResponseExceptionFilter))]
[TypeFilter(typeof(AngularJsonOnlyConfigurationAttribute))]
[HttpInstallAuthorize]
[Area("Install")]
[Area(Umbraco.Core.Constants.Web.Mvc.InstallArea)]
public class InstallApiController : ControllerBase
{
private readonly DatabaseBuilder _databaseBuilder;

View File

@@ -14,12 +14,10 @@ namespace Umbraco.Web.Common.Install
{
/// <summary>
/// The MVC Installation controller
/// The Installation controller
/// </summary>
/// <remarks>
/// NOTE: All views must have their full paths as we do not have a custom view engine for the installation views!
/// </remarks>
[InstallAuthorize]
[Area(Umbraco.Core.Constants.Web.Mvc.InstallArea)]
public class InstallController : Controller
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
@@ -72,7 +70,7 @@ namespace Umbraco.Web.Common.Install
}
// gen the install base urlAddUmbracoCore
ViewData.SetInstallApiBaseUrl(Url.GetUmbracoApiService("GetSetup", "InstallApi", "UmbracoInstall").TrimEnd("GetSetup"));
ViewData.SetInstallApiBaseUrl(Url.GetUmbracoApiService("GetSetup", "InstallApi", Umbraco.Core.Constants.Web.Mvc.InstallArea).TrimEnd("GetSetup"));
// get the base umbraco folder
ViewData.SetUmbracoBaseFolder(_hostingEnvironment.ToAbsolute(_globalSettings.UmbracoPath));
@@ -81,7 +79,6 @@ namespace Umbraco.Web.Common.Install
await _installHelper.InstallStatus(false, "");
// always ensure full path (see NOTE in the class remarks)
return View();
}
}

View File

@@ -8,30 +8,28 @@ using Umbraco.Core.Logging.Serilog.Enrichers;
namespace Umbraco.Web.Common.Middleware
{
public class UmbracoRequestLoggingMiddleware
public class UmbracoRequestLoggingMiddleware : IMiddleware
{
readonly RequestDelegate _next;
private readonly HttpSessionIdEnricher _sessionIdEnricher;
private readonly HttpRequestNumberEnricher _requestNumberEnricher;
private readonly HttpRequestIdEnricher _requestIdEnricher;
public UmbracoRequestLoggingMiddleware(RequestDelegate next,
public UmbracoRequestLoggingMiddleware(
HttpSessionIdEnricher sessionIdEnricher,
HttpRequestNumberEnricher requestNumberEnricher,
HttpRequestIdEnricher requestIdEnricher)
{
_next = next;
_sessionIdEnricher = sessionIdEnricher;
_requestNumberEnricher = requestNumberEnricher;
_requestIdEnricher = requestIdEnricher;
}
public async Task Invoke(HttpContext httpContext)
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// do not process if client-side request
if (new Uri(httpContext.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsClientSideRequest())
if (new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsClientSideRequest())
{
await _next(httpContext);
await next(context);
return;
}
@@ -42,7 +40,7 @@ namespace Umbraco.Web.Common.Middleware
using (LogContext.Push(_requestNumberEnricher))
using (LogContext.Push(_requestIdEnricher))
{
await _next(httpContext);
await next(context);
}
}
}

View File

@@ -5,46 +5,46 @@ using Microsoft.AspNetCore.Http.Extensions;
using Umbraco.Web.Common.Lifetime;
using Umbraco.Core;
using Umbraco.Core.Logging;
using System.Threading;
namespace Umbraco.Web.Common.Middleware
{
/// <summary>
/// Manages Umbraco request objects and their lifetime
/// </summary>
public class UmbracoRequestMiddleware
public class UmbracoRequestMiddleware : IMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly IUmbracoRequestLifetimeManager _umbracoRequestLifetimeManager;
private readonly IUmbracoContextFactory _umbracoContextFactory;
public UmbracoRequestMiddleware(RequestDelegate next,
public UmbracoRequestMiddleware(
ILogger logger,
IUmbracoRequestLifetimeManager umbracoRequestLifetimeManager,
IUmbracoContextFactory umbracoContextFactory)
{
_next = next;
_logger = logger;
_umbracoRequestLifetimeManager = umbracoRequestLifetimeManager;
_umbracoContextFactory = umbracoContextFactory;
}
public async Task InvokeAsync(HttpContext context)
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// do not process if client-side request
if (new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsClientSideRequest())
{
await _next(context);
await next(context);
return;
}
var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();
try
{
try
{
{
_umbracoRequestLifetimeManager.InitRequest(context);
}
catch (Exception ex)
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Common.Middleware
_logger.Error<UmbracoRequestMiddleware>(ex);
}
await _next(context);
await next(context);
_umbracoRequestLifetimeManager.EndRequest(context);
}

View File

@@ -99,10 +99,5 @@ namespace Umbraco.Web
return new UmbracoContextReference(umbracoContext, true, _umbracoContextAccessor);
}
// dummy TextWriter that does not write
private class NullWriter : TextWriter
{
public override Encoding Encoding => Encoding.UTF8;
}
}
}

View File

@@ -1,4 +1,4 @@
@using Umbraco.Web
@using Umbraco.Extensions
@using Umbraco.Composing
@{
Layout = null;

View File

@@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace Umbraco.Web.UI.BackOffice
{
public class HomeController : Controller
{
// GET: /<controller>/
public IActionResult Index()
{
return View();
}
}
}

View File

@@ -1,30 +1,10 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using Umbraco.Composing;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Extensions;
using Umbraco.Web.Common.Filters;
using Umbraco.Web.Website.AspNetCore;
using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Web.UI.BackOffice
{
@@ -62,24 +42,11 @@ namespace Umbraco.Web.UI.BackOffice
{
options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile
});
//Finally initialize Current
// TODO: This should be moved to the UmbracoServiceProviderFactory when the container is cross-wired and then don't use the overload above to `out var factory`
Current.Initialize(
factory.GetInstance<ILogger> (),
factory.GetInstance<Configs>(),
factory.GetInstance<IIOHelper>(),
factory.GetInstance<IHostingEnvironment>(),
factory.GetInstance<IBackOfficeInfo>(),
factory.GetInstance<IProfiler>()
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
//app.UseMiniProfiler();
if (_env.IsDevelopment())
{
@@ -89,29 +56,15 @@ namespace Umbraco.Web.UI.BackOffice
app.UseStatusCodePages();
app.UseRouting();
app.UseUmbracoRouting();
app.UseUmbracoCore();
app.UseUmbracoRouting();
app.UseUmbracoRequestLogging();
app.UseUmbracoWebsite();
app.UseUmbracoBackOffice();
app.UseUmbracoRuntimeMinification();
app.UseUmbracoBackOffice();
app.UseUmbracoInstaller();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("Backoffice", "/umbraco/{Action}", new
{
Controller = "BackOffice",
Action = "Default"
});
// TODO: Fix this routing with an area
endpoints.MapControllerRoute("Install", "/install/{controller}/{Action}", defaults:new { Area = "Install"});
//TODO register routing correct: Name must be like this
endpoints.MapControllerRoute("umbraco-api-UmbracoInstall-InstallApi", "/install/api/{Action}", defaults:new { Area = "Install", Controller = "InstallApi"});
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");

View File

@@ -13,6 +13,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Views\" />
<Folder Include="wwwroot\Media" />
<Folder Include="wwwroot\Umbraco\views\install" />
</ItemGroup>
@@ -40,7 +41,7 @@
<Content Remove="wwwroot\Umbraco\views\install\continueinstall.html" />
<Content Remove="wwwroot\Umbraco\views\install\database.html" />
<Content Remove="wwwroot\Umbraco\views\install\error.html" />
<Content Update="Views\Install\Index.cshtml">
<Content Update="Areas\UmbracoInstall\Views\Install\Index.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>

View File

@@ -1,13 +1,10 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using SixLabors.ImageSharp.Web.DependencyInjection;
using Umbraco.Core;
using Umbraco.Extensions;
namespace Umbraco.Web.Website.AspNetCore
namespace Umbraco.Extensions
{
public static class UmbracoBackOfficeApplicationBuilderExtensions
public static class UmbracoWebsiteApplicationBuilderExtensions
{
public static IApplicationBuilder UseUmbracoWebsite(this IApplicationBuilder app)
{
@@ -16,6 +13,7 @@ namespace Umbraco.Web.Website.AspNetCore
if (!app.UmbracoCanBoot()) return app;
// 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();