using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Web.Website.Controllers; using Umbraco.Extensions; using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; namespace Umbraco.Cms.Web.UI.Composers { /// /// Adds controllers to the service collection. /// /// /// /// Umbraco 9 out of the box, makes use of which doesn't resolve controller /// instances from the IOC container, instead it resolves the required dependencies of the controller and constructs an instance /// of the controller. /// /// /// Some users may wish to switch to (perhaps to make use of interception/decoration). /// /// /// This composer exists to help us detect ambiguous constructors in the CMS such that we do not cause unnecessary effort downstream. /// /// /// This Composer is not shipped by the Umbraco.Templates package. /// /// public class ControllersAsServicesComposer : IComposer { /// public void Compose(IUmbracoBuilder builder) => builder.Services .AddMvc() .AddControllersAsServicesWithoutChangingActivator(); } internal static class MvcBuilderExtensions { /// /// but without the replacement of /// . /// /// /// We don't need to opt in to to ensure container validation /// passes. /// public static IMvcBuilder AddControllersAsServicesWithoutChangingActivator(this IMvcBuilder builder) { var feature = new ControllerFeature(); builder.PartManager.PopulateFeature(feature); foreach (Type controller in feature.Controllers.Select(c => c.AsType())) { builder.Services.TryAddTransient(controller, controller); } builder.Services.AddUnique(x => new RenderNoContentController(x.GetService()!, x.GetService>()!, x.GetService()!)); return builder; } } }