Files
Umbraco-CMS/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs

123 lines
4.9 KiB
C#

using System;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
using Umbraco.Web.BackOffice.Controllers;
using Umbraco.Web.Common.Controllers;
using Umbraco.Web.Common.Extensions;
using Umbraco.Web.Common.Routing;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Routing
{
/// <summary>
/// Creates routes for the back office area
/// </summary>
public sealed class BackOfficeAreaRoutes : IAreaRoutes
{
private readonly GlobalSettings _globalSettings;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IRuntimeState _runtimeState;
private readonly UmbracoApiControllerTypeCollection _apiControllers;
private readonly string _umbracoPathSegment;
/// <summary>
/// Initializes a new instance of the <see cref="BackOfficeAreaRoutes"/> class.
/// </summary>
public BackOfficeAreaRoutes(
IOptions<GlobalSettings> globalSettings,
IHostingEnvironment hostingEnvironment,
IRuntimeState runtimeState,
UmbracoApiControllerTypeCollection apiControllers)
{
_globalSettings = globalSettings.Value;
_hostingEnvironment = hostingEnvironment;
_runtimeState = runtimeState;
_apiControllers = apiControllers;
_umbracoPathSegment = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment);
}
/// <inheritdoc/>
public void CreateRoutes(IEndpointRouteBuilder endpoints)
{
switch (_runtimeState.Level)
{
case RuntimeLevel.Install:
// a new install so we don't route the back office
break;
case RuntimeLevel.Upgrade:
// for upgrades we only need to route the back office and auth controllers
MapMinimalBackOffice(endpoints);
break;
case RuntimeLevel.Run:
MapMinimalBackOffice(endpoints);
AutoRouteBackOfficeApiControllers(endpoints);
break;
case RuntimeLevel.BootFailed:
case RuntimeLevel.Unknown:
case RuntimeLevel.Boot:
break;
}
}
/// <summary>
/// Map the minimal routes required to load the back office login and auth
/// </summary>
private void MapMinimalBackOffice(IEndpointRouteBuilder endpoints)
{
endpoints.MapUmbracoRoute<BackOfficeController>(
_umbracoPathSegment,
Constants.Web.Mvc.BackOfficeArea,
string.Empty,
"Default",
includeControllerNameInRoute: false,
constraints:
// Limit the action/id to only allow characters - this is so this route doesn't hog all other
// routes like: /umbraco/channels/word.aspx, etc...
// (Not that we have to worry about too many of those these days, there still might be a need for these constraints).
new
{
action = @"[a-zA-Z]*",
id = @"[a-zA-Z]*"
});
endpoints.MapUmbracoApiRoute<AuthenticationController>(_umbracoPathSegment, Constants.Web.Mvc.BackOfficeApiArea, true, defaultAction: string.Empty);
}
/// <summary>
/// Auto-routes all back office api controllers
/// </summary>
private void AutoRouteBackOfficeApiControllers(IEndpointRouteBuilder endpoints)
{
// TODO: We could investigate dynamically routing plugin controllers so we don't have to eagerly type scan for them,
// it would probably work well, see https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/
// will probably be what we use for front-end routing too. BTW the orig article about migrating from IRouter to endpoint
// routing for things like a CMS is here https://github.com/dotnet/aspnetcore/issues/4221
foreach (Type controller in _apiControllers)
{
PluginControllerMetadata meta = PluginController.GetMetadata(controller);
// exclude front-end api controllers
if (!meta.IsBackOffice)
{
continue;
}
endpoints.MapUmbracoApiRoute(
meta.ControllerType,
_umbracoPathSegment,
meta.AreaName,
meta.IsBackOffice,
defaultAction: string.Empty); // no default action (this is what we had before)
}
}
}
}