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;