diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs
index cbf12f54a3..01f7902c2e 100644
--- a/src/Umbraco.Core/Composing/IRegister.cs
+++ b/src/Umbraco.Core/Composing/IRegister.cs
@@ -94,7 +94,7 @@ namespace Umbraco.Core.Composing
/// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot
/// process, where anything "scoped" should not be linked to a web request.
///
- void ConfigureForWeb();
+ void ConfigureForWeb(); // TODO: Unsure if we need this anymore
///
/// Creates the factory.
diff --git a/src/Umbraco.Core/Trees/ITree.cs b/src/Umbraco.Core/Trees/ITree.cs
index 7cd7e4221a..567accbd9e 100644
--- a/src/Umbraco.Core/Trees/ITree.cs
+++ b/src/Umbraco.Core/Trees/ITree.cs
@@ -1,7 +1,8 @@
namespace Umbraco.Web.Trees
{
// TODO: we don't really use this, it is nice to have the treecontroller, attribute and ApplicationTree streamlined to implement this but it's not used
- //leave as internal for now, maybe we'll use in the future, means we could pass around ITree
+ // leave as internal for now, maybe we'll use in the future, means we could pass around ITree
+ // TODO: We should make this a thing, a tree should just be an interface *not* a controller
internal interface ITree
{
///
diff --git a/src/Umbraco.Core/Models/PluginControllerMetadata.cs b/src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs
similarity index 100%
rename from src/Umbraco.Core/Models/PluginControllerMetadata.cs
rename to src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs
diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs
index 7b6d8c864c..a6cd372411 100644
--- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs
+++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Integration.Implementations
var httpContext = new DefaultHttpContext();
httpContext.Connection.RemoteIpAddress = IPAddress.Parse("127.0.0.1");
_httpContextAccessor = Mock.Of(x => x.HttpContext == httpContext);
- _ipResolver = new AspNetIpResolver(_httpContextAccessor);
+ _ipResolver = new AspNetCoreIpResolver(_httpContextAccessor);
var hostEnvironment = new Mock();
hostEnvironment.Setup(x => x.ApplicationName).Returns("UmbracoIntegrationTests");
diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
index ae8470ea33..2f87ee8b6f 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
@@ -1,13 +1,14 @@
using Microsoft.AspNetCore.Mvc;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Filters;
+using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Controllers
{
- [Area(Umbraco.Core.Constants.Web.Mvc.BackOfficeArea)]
+ [Area(Constants.Web.Mvc.BackOfficeArea)] // TODO: Maybe this could be applied with our Application Model conventions
//[ValidationFilter] // TODO: I don't actually think this is required with our custom Application Model conventions applied
- [TypeFilter(typeof(AngularJsonOnlyConfigurationAttribute))]
- [IsBackOffice]
+ [TypeFilter(typeof(AngularJsonOnlyConfigurationAttribute))] // TODO: This could be applied with our Application Model conventions
+ [IsBackOffice] // TODO: This could be applied with our Application Model conventions
public class AuthenticationController : ControllerBase
{
// TODO: We need to import the logic from Umbraco.Web.Editors.AuthenticationController and it should not be an auto-routed api controller
diff --git a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs
index 59d5b68010..457a5dc214 100644
--- a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs
+++ b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs
@@ -3,23 +3,34 @@ using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Web.BackOffice.Controllers;
+using Umbraco.Web.Common.Controllers;
using Umbraco.Web.Common.Routing;
+using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Routing
{
+ ///
+ /// Creates routes for the back office area
+ ///
public class BackOfficeAreaRoutes : IAreaRoutes
{
private readonly IGlobalSettings _globalSettings;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IRuntimeState _runtimeState;
- private readonly string _umbracoAreaPathSegment;
+ private readonly UmbracoApiControllerTypeCollection _apiControllers;
+ private readonly string _umbracoPathSegment;
- public BackOfficeAreaRoutes(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState)
+ public BackOfficeAreaRoutes(
+ IGlobalSettings globalSettings,
+ IHostingEnvironment hostingEnvironment,
+ IRuntimeState runtimeState,
+ UmbracoApiControllerTypeCollection apiControllers)
{
_globalSettings = globalSettings;
_hostingEnvironment = hostingEnvironment;
_runtimeState = runtimeState;
- _umbracoAreaPathSegment = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment);
+ _apiControllers = apiControllers;
+ _umbracoPathSegment = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment);
}
public void CreateRoutes(IEndpointRouteBuilder endpoints)
@@ -36,7 +47,7 @@ namespace Umbraco.Web.BackOffice.Routing
case RuntimeLevel.Run:
MapMinimalBackOffice(endpoints);
- endpoints.MapUmbracoRoute(_umbracoAreaPathSegment, Constants.Web.Mvc.BackOfficeArea, "preview");
+ endpoints.MapUmbracoRoute(_umbracoPathSegment, Constants.Web.Mvc.BackOfficeArea, "preview");
AutoRouteBackOfficeControllers(endpoints);
break;
@@ -53,7 +64,7 @@ namespace Umbraco.Web.BackOffice.Routing
///
private void MapMinimalBackOffice(IEndpointRouteBuilder endpoints)
{
- endpoints.MapUmbracoRoute(_umbracoAreaPathSegment, Constants.Web.Mvc.BackOfficeArea,
+ endpoints.MapUmbracoRoute(_umbracoPathSegment, Constants.Web.Mvc.BackOfficeArea,
string.Empty,
"Default",
constraints:
@@ -66,7 +77,7 @@ namespace Umbraco.Web.BackOffice.Routing
id = @"[a-zA-Z]*"
});
- endpoints.MapUmbracoRoute(_umbracoAreaPathSegment, Constants.Web.Mvc.BackOfficeArea, true);
+ endpoints.MapUmbracoApiRoute(_umbracoPathSegment, Constants.Web.Mvc.BackOfficeArea, true, defaultAction: string.Empty);
}
///
@@ -74,7 +85,24 @@ namespace Umbraco.Web.BackOffice.Routing
///
private void AutoRouteBackOfficeControllers(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 (var controller in _apiControllers)
+ {
+ // exclude front-end api controllers
+ var meta = PluginController.GetMetadata(controller);
+ if (!meta.IsBackOffice) continue;
+
+ endpoints.MapUmbracoApiRoute(
+ meta.ControllerType,
+ _umbracoPathSegment,
+ meta.AreaName,
+ true,
+ defaultAction: string.Empty); // no default action (this is what we had before)
+ }
}
}
}
diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
index 73fa06f1c7..33b6fc5f2e 100644
--- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
+++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
@@ -1,5 +1,7 @@
-using Umbraco.Core;
+using System.Linq;
+using Umbraco.Core;
using Umbraco.Core.Composing;
+using Umbraco.Extensions;
using Umbraco.Web.BackOffice.Routing;
namespace Umbraco.Web.BackOffice.Runtime
diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreIpResolver.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreIpResolver.cs
index 863d545066..3628478682 100644
--- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreIpResolver.cs
+++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreIpResolver.cs
@@ -3,11 +3,11 @@ using Umbraco.Net;
namespace Umbraco.Web.Common.AspNetCore
{
- public class AspNetIpResolver : IIpResolver
+ public class AspNetCoreIpResolver : IIpResolver
{
private readonly IHttpContextAccessor _httpContextAccessor;
- public AspNetIpResolver(IHttpContextAccessor httpContextAccessor)
+ public AspNetCoreIpResolver(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
diff --git a/src/Umbraco.Web.Common/Attributes/IsBackOfficeAttribute.cs b/src/Umbraco.Web.Common/Attributes/IsBackOfficeAttribute.cs
index b625bd3336..2c017a5978 100644
--- a/src/Umbraco.Web.Common/Attributes/IsBackOfficeAttribute.cs
+++ b/src/Umbraco.Web.Common/Attributes/IsBackOfficeAttribute.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.AspNetCore.Mvc;
+using System;
namespace Umbraco.Web.Common.Attributes
{
@@ -8,6 +9,6 @@ namespace Umbraco.Web.Common.Attributes
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class IsBackOfficeAttribute : Attribute
- {
+ {
}
}
diff --git a/src/Umbraco.Web.Common/Attributes/PluginControllerAttribute.cs b/src/Umbraco.Web.Common/Attributes/PluginControllerAttribute.cs
index 8ebc12cc1f..4844200ebf 100644
--- a/src/Umbraco.Web.Common/Attributes/PluginControllerAttribute.cs
+++ b/src/Umbraco.Web.Common/Attributes/PluginControllerAttribute.cs
@@ -1,19 +1,20 @@
-using System;
+using Microsoft.AspNetCore.Mvc;
+using System;
using System.Linq;
namespace Umbraco.Web.Common.Attributes
{
///
- /// Indicates that a controller is a plugin controller and should be routed to its own area.
+ /// Indicates that a controller is a plugin controller and will be routed to its own area.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class PluginControllerAttribute : Attribute
+ public class PluginControllerAttribute : AreaAttribute
{
///
/// Initializes a new instance of the class.
///
///
- public PluginControllerAttribute(string areaName)
+ public PluginControllerAttribute(string areaName) : base(areaName)
{
// validate this, only letters and digits allowed.
if (areaName.Any(c => !char.IsLetterOrDigit(c)))
diff --git a/src/Umbraco.Web.Common/Controllers/PluginController.cs b/src/Umbraco.Web.Common/Controllers/PluginController.cs
index c5be42ea88..f78fa1a7e4 100644
--- a/src/Umbraco.Web.Common/Controllers/PluginController.cs
+++ b/src/Umbraco.Web.Common/Controllers/PluginController.cs
@@ -79,7 +79,7 @@ namespace Umbraco.Web.Common.Controllers
///
/// The controller type.
/// Metadata for the controller type.
- internal static PluginControllerMetadata GetMetadata(Type controllerType)
+ public static PluginControllerMetadata GetMetadata(Type controllerType)
{
return MetadataStorage.GetOrAdd(controllerType, type =>
{
diff --git a/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerBase.cs b/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerBase.cs
index 01300d1fa5..5a38d6c0ab 100644
--- a/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerBase.cs
+++ b/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerBase.cs
@@ -14,8 +14,8 @@ namespace Umbraco.Web.Common.Controllers
/// These controllers are NOT auto-routed.
/// The base class is which are netcore API controllers without any view support
///
- [FeatureAuthorize]
- [TypeFilter(typeof(HttpResponseExceptionFilter))]
+ [FeatureAuthorize] // TODO: This could be part of our conventions
+ [TypeFilter(typeof(HttpResponseExceptionFilter))] // TODO: This could be part of our conventions
[UmbracoApiController]
public abstract class UmbracoApiControllerBase : ControllerBase, IUmbracoFeature
{
diff --git a/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerTypeCollectionBuilder.cs b/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerTypeCollectionBuilder.cs
new file mode 100644
index 0000000000..4bffb0d5ba
--- /dev/null
+++ b/src/Umbraco.Web.Common/Controllers/UmbracoApiControllerTypeCollectionBuilder.cs
@@ -0,0 +1,10 @@
+using Umbraco.Core.Composing;
+using Umbraco.Web.WebApi;
+
+namespace Umbraco.Web.Common.Controllers
+{
+ public class UmbracoApiControllerTypeCollectionBuilder : TypeCollectionBuilderBase
+ {
+ protected override UmbracoApiControllerTypeCollectionBuilder This => this;
+ }
+}
diff --git a/src/Umbraco.Web.Common/Extensions/TypeLoaderExtensions.cs b/src/Umbraco.Web.Common/Extensions/TypeLoaderExtensions.cs
new file mode 100644
index 0000000000..e800150c27
--- /dev/null
+++ b/src/Umbraco.Web.Common/Extensions/TypeLoaderExtensions.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Umbraco.Core.Composing;
+using Umbraco.Web.Common.Controllers;
+
+namespace Umbraco.Extensions
+{
+ public static class TypeLoaderExtensions
+ {
+ ///
+ /// Gets all types implementing .
+ ///
+ public static IEnumerable GetUmbracoApiControllers(this TypeLoader typeLoader)
+ => typeLoader.GetTypes();
+ }
+}
diff --git a/src/Umbraco.Web.Common/Install/InstallerComposer.cs b/src/Umbraco.Web.Common/Install/InstallerComposer.cs
deleted file mode 100644
index d71a7a571e..0000000000
--- a/src/Umbraco.Web.Common/Install/InstallerComposer.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Umbraco.Core;
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Web.Common.Install
-{
- public class InstallerComposer : IComposer
- {
- public void Compose(Composition composition)
- {
- composition.RegisterUnique();
- }
- }
-}
diff --git a/src/Umbraco.Web.Common/Routing/EndpointRouteBuilderExtensions.cs b/src/Umbraco.Web.Common/Routing/EndpointRouteBuilderExtensions.cs
index 49b8af52af..aa7c9195dd 100644
--- a/src/Umbraco.Web.Common/Routing/EndpointRouteBuilderExtensions.cs
+++ b/src/Umbraco.Web.Common/Routing/EndpointRouteBuilderExtensions.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using NUglify.Helpers;
+using System;
using System.Text;
using Umbraco.Extensions;
@@ -9,6 +10,64 @@ namespace Umbraco.Web.Common.Routing
{
public static class EndpointRouteBuilderExtensions
{
+ ///
+ /// Used to map Umbraco controllers consistently
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void MapUmbracoRoute(
+ this IEndpointRouteBuilder endpoints,
+ Type controllerType,
+ string rootSegment,
+ string areaName,
+ string prefixPathSegment,
+ string defaultAction = "Index",
+ bool includeControllerNameInRoute = true,
+ object constraints = null)
+ {
+ var controllerName = ControllerExtensions.GetControllerName(controllerType);
+
+ // build the route pattern
+ var pattern = new StringBuilder(rootSegment);
+ if (!prefixPathSegment.IsNullOrWhiteSpace())
+ pattern.Append("/").Append(prefixPathSegment);
+ if (includeControllerNameInRoute)
+ pattern.Append("/").Append(controllerName);
+ pattern.Append("/").Append("{action}/{id?}");
+
+ var defaults = defaultAction.IsNullOrWhiteSpace()
+ ? (object) new { controller = controllerName }
+ : new { controller = controllerName, action = defaultAction };
+
+
+ if (areaName.IsNullOrWhiteSpace())
+ {
+ endpoints.MapControllerRoute(
+ // named consistently
+ $"umbraco-{areaName}-{controllerName}".ToLowerInvariant(),
+ pattern.ToString().ToLowerInvariant(),
+ defaults,
+ constraints);
+ }
+ else
+ {
+ endpoints.MapAreaControllerRoute(
+ // named consistently
+ $"umbraco-{areaName}-{controllerName}".ToLowerInvariant(),
+ areaName,
+ pattern.ToString().ToLowerInvariant(),
+ defaults,
+ constraints);
+ }
+
+ }
+
///
/// Used to map Umbraco controllers consistently
///
@@ -28,43 +87,49 @@ namespace Umbraco.Web.Common.Routing
bool includeControllerNameInRoute = true,
object constraints = null)
where T : ControllerBase
- {
- var controllerName = ControllerExtensions.GetControllerName();
-
- // build the route pattern
- var pattern = new StringBuilder(rootSegment);
- if (!prefixPathSegment.IsNullOrWhiteSpace())
- pattern.Append("/").Append(prefixPathSegment);
- if (includeControllerNameInRoute)
- pattern.Append("/").Append(controllerName);
- pattern.Append("/").Append("{action}/{id?}");
-
- endpoints.MapAreaControllerRoute(
- // named consistently
- $"umbraco-{areaName}-{controllerName}".ToLowerInvariant(),
- areaName,
- pattern.ToString().ToLowerInvariant(),
- new { controller = controllerName, action = defaultAction },
- constraints);
- }
+ => endpoints.MapUmbracoRoute(typeof(T), rootSegment, areaName, prefixPathSegment, defaultAction, includeControllerNameInRoute, constraints);
///
- /// Used to map Umbraco controllers consistently
+ /// Used to map Umbraco api controllers consistently
///
///
///
- ///
+ ///
///
- ///
+ /// If the route is a back office route
///
- public static void MapUmbracoRoute(
+ public static void MapUmbracoApiRoute(
this IEndpointRouteBuilder endpoints,
- string rootPathSegment,
+ string rootSegment,
string areaName,
bool isBackOffice,
string defaultAction = "Index",
object constraints = null)
where T : ControllerBase
- => endpoints.MapUmbracoRoute(rootPathSegment, areaName, isBackOffice ? "BackOffice" : "Api", defaultAction, true, constraints);
+ => endpoints.MapUmbracoRoute(typeof(T), rootSegment, areaName, isBackOffice ? "BackOffice/Api" : "Api", defaultAction, true, constraints);
+
+ ///
+ /// Used to map Umbraco api controllers consistently
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// If the route is a back office route
+ ///
+ ///
+ public static void MapUmbracoApiRoute(
+ this IEndpointRouteBuilder endpoints,
+ Type controllerType,
+ string rootSegment,
+ string areaName,
+ bool isBackOffice,
+ string defaultAction = "Index",
+ object constraints = null)
+ => endpoints.MapUmbracoRoute(controllerType, rootSegment, areaName,
+ isBackOffice
+ ? (areaName.IsNullOrWhiteSpace() ? "BackOffice/Api" : $"BackOffice/{areaName}")
+ : (areaName.IsNullOrWhiteSpace() ? "Api" : areaName),
+ defaultAction, true, constraints);
}
}
diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
index 78068b551c..c2a29c63a6 100644
--- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
+++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
@@ -14,6 +14,10 @@ using Umbraco.Web.Macros;
using Umbraco.Core.Diagnostics;
using Umbraco.Core.Logging;
using Umbraco.Web.Common.Profiler;
+using Umbraco.Web.Common.Install;
+using Umbraco.Extensions;
+using System.Linq;
+using Umbraco.Web.Common.Controllers;
namespace Umbraco.Web.Common.Runtime
{
@@ -40,12 +44,12 @@ namespace Umbraco.Web.Common.Runtime
// The umbraco request lifetime
composition.RegisterMultipleUnique();
-
//Password hasher
composition.RegisterUnique();
composition.RegisterUnique();
+ composition.Register();
composition.RegisterUnique();
composition.RegisterMultipleUnique();
@@ -67,6 +71,12 @@ namespace Umbraco.Web.Common.Runtime
//it still needs to use the install controller so we can't do that
composition.ComposeInstaller();
+ var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList();
+ composition.WithCollectionBuilder()
+ .Add(umbracoApiControllerTypes);
+
+ composition.RegisterUnique();
+
}
}
}
diff --git a/src/Umbraco.Web.UI.NetCore/Controllers/TestBackOfficeUmbracoApiController.cs b/src/Umbraco.Web.UI.NetCore/Controllers/TestBackOfficeUmbracoApiController.cs
new file mode 100644
index 0000000000..d5cddb508a
--- /dev/null
+++ b/src/Umbraco.Web.UI.NetCore/Controllers/TestBackOfficeUmbracoApiController.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Umbraco.Web.Common.Attributes;
+using Umbraco.Web.Common.Controllers;
+
+namespace Umbraco.Web.UI.NetCore.Controllers
+{
+ [PluginController("Test")]
+ [IsBackOffice]
+ public class TestBackOfficeUmbracoApiController : UmbracoApiController
+ {
+ [HttpGet]
+ public IActionResult Index()
+ {
+ return Content("hello world");
+ }
+ }
+}
diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs
index 3a86978e17..27b54a9503 100644
--- a/src/Umbraco.Web.UI.NetCore/Startup.cs
+++ b/src/Umbraco.Web.UI.NetCore/Startup.cs
@@ -30,7 +30,14 @@ namespace Umbraco.Web.UI.BackOffice
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
- {
+ {
+ // TODO: We will need to decide on if we want to use the ServiceBasedControllerActivator to create our controllers
+ // or use the default IControllerActivator: DefaultControllerActivator (which doesn't directly use the container to resolve controllers)
+ // This will affect whether we need to explicitly register controllers in the container like we do today in v8.
+ // What we absolutely must do though is make sure we explicitly opt-in to using one or the other *always* for our controllers instead of
+ // relying on a global configuration set by a user since if a custom IControllerActivator is used for our own controllers we may not
+ // guarantee it will work. And then... is that even possible?
+
services.AddUmbracoConfiguration(_config);
services.AddUmbracoCore(_env, out var factory);
services.AddUmbracoWebComponents();
diff --git a/src/Umbraco.Web/Mvc/PluginControllerAttribute.cs b/src/Umbraco.Web/Mvc/PluginControllerAttribute.cs
index 332f1fd2a9..aedc472111 100644
--- a/src/Umbraco.Web/Mvc/PluginControllerAttribute.cs
+++ b/src/Umbraco.Web/Mvc/PluginControllerAttribute.cs
@@ -3,9 +3,8 @@ using System.Linq;
namespace Umbraco.Web.Mvc
{
- ///
- /// Indicates that a controller is a plugin tree controller and should be routed to its own area.
- ///
+ // TODO: This has been moved to netcore so can be removed when ready
+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginControllerAttribute : Attribute
{
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index 0e5bc7a7bb..a427669ed9 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -1,19 +1,13 @@
using System.Linq;
using System.Web.Security;
-using Examine;
using Microsoft.AspNet.SignalR;
using Umbraco.Core;
using Umbraco.Core.Composing;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.Install;
using Umbraco.Core.Runtime;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Composing.CompositionExtensions;
-using Umbraco.Web.Hosting;
-using Umbraco.Web.Install;
using Umbraco.Web.Macros;
using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
@@ -22,12 +16,6 @@ using Umbraco.Web.Security.Providers;
using Umbraco.Web.SignalR;
using Umbraco.Web.Templates;
using Umbraco.Web.Trees;
-using Umbraco.Web.WebApi;
-using Umbraco.Net;
-using Umbraco.Web.AspNet;
-using Umbraco.Core.Diagnostics;
-using Umbraco.Core.Logging;
-using Umbraco.Web.Logging;
namespace Umbraco.Web.Runtime
{
@@ -41,28 +29,9 @@ namespace Umbraco.Web.Runtime
base.Compose(composition);
composition.Register();
- composition.Register();
-
- composition.Register();
-
-
- composition.Register(Lifetime.Singleton);
-
- composition.Register(Lifetime.Singleton);
- composition.Register();
-
-
-
- composition.RegisterUnique();
- composition.RegisterUnique();
composition.ComposeWebMappingProfiles();
- //register the install components
- //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts
- //it still needs to use the install controller so we can't do that
- composition.ComposeInstaller();
-
// register membership stuff
composition.Register(factory => MembershipProviderExtensions.GetMembersMembershipProvider());
composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance()));
@@ -71,11 +40,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterUnique();
composition.RegisterUnique();
- // register the umbraco context factory
- composition.RegisterUnique();
-
composition.RegisterUnique();
- composition.RegisterUnique();
composition.RegisterUnique();
@@ -98,16 +63,14 @@ namespace Umbraco.Web.Runtime
composition.ConfigureForWeb();
composition
+ // TODO: This will depend on if we use ServiceBasedControllerActivator - see notes in Startup.cs
.ComposeUmbracoControllers(GetType().Assembly)
.SetDefaultRenderMvcController(); // default controller for template views
//we need to eagerly scan controller types since they will need to be routed
composition.WithCollectionBuilder()
.Add(composition.TypeLoader.GetSurfaceControllers());
- var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList();
- composition.WithCollectionBuilder()
- .Add(umbracoApiControllerTypes);
-
+
// add all known factories, devs can then modify this list on application
// startup either by binding to events or in their own global.asax
@@ -120,6 +83,8 @@ namespace Umbraco.Web.Runtime
// register preview SignalR hub
composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext());
+ var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList();
+
// register back office trees
// the collection builder only accepts types inheriting from TreeControllerBase
// and will filter out those that are not attributed with TreeAttribute
@@ -127,18 +92,6 @@ namespace Umbraco.Web.Runtime
.AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x)));
-
- // STUFF that do not have to be moved to .NET CORE
- //----------------------------------------
- composition.RegisterUnique();
- composition.RegisterUnique();
- composition.RegisterUnique();
- composition.RegisterUnique(); // required for hybrid accessors
-
- composition.Register(Lifetime.Singleton);
- composition.Register(factory => factory.GetInstance(), Lifetime.Singleton);
- composition.Register(factory => factory.GetInstance(), Lifetime.Singleton);
-
}
}
}
diff --git a/src/Umbraco.Web/WebApi/IsBackOfficeAttribute.cs b/src/Umbraco.Web/WebApi/IsBackOfficeAttribute.cs
index 2d0b194022..49b707bf3a 100644
--- a/src/Umbraco.Web/WebApi/IsBackOfficeAttribute.cs
+++ b/src/Umbraco.Web/WebApi/IsBackOfficeAttribute.cs
@@ -2,10 +2,8 @@
namespace Umbraco.Web.WebApi
{
- ///
- /// When applied to an api controller it will be routed to the /Umbraco/BackOffice prefix route so we can determine if it
- /// is a back office route or not.
- ///
+ // TODO: This has been moved to netcore so can be removed when ready
+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class IsBackOfficeAttribute : Attribute
{
diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollectionBuilder.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollectionBuilder.cs
index a9cf7b4619..899b1af4d7 100644
--- a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollectionBuilder.cs
+++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollectionBuilder.cs
@@ -2,6 +2,8 @@
namespace Umbraco.Web.WebApi
{
+ // TODO: This is moved to netcore so can be deleted when possible
+
public class UmbracoApiControllerTypeCollectionBuilder : TypeCollectionBuilderBase
{
protected override UmbracoApiControllerTypeCollectionBuilder This => this;