using System.Linq; using System.Web; using System.Web.Security; using Examine; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Dashboards; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Runtime; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Cache; using Umbraco.Web.Composing.Composers; using Umbraco.Web.ContentApps; using Umbraco.Web.Dashboards; using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Search; using Umbraco.Web.Security; using Umbraco.Web.Security.Providers; using Umbraco.Web.Services; using Umbraco.Web.SignalR; using Umbraco.Web.Tour; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Runtime { [ComposeAfter(typeof(CoreRuntimeComposer))] public sealed class WebRuntimeComposer : ComponentComposer, IRuntimeComposer { public override void Compose(Composition composition) { base.Compose(composition); composition.Register(); composition.RegisterUnique(); // required for hybrid accessors 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 => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); composition.Register(); // register accessors for cultures composition.RegisterUnique(); composition.RegisterUnique(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. composition.RegisterUnique(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request composition.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.RegisterUnique(); // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register // a way to inject the UmbracoContext - and register it per-request to be more efficient // TODO: stop doing this composition.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper composition.RegisterUnique(); // register distributed cache composition.RegisterUnique(f => new DistributedCache()); // replace some services composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(factory => ExamineManager.Instance); // configure the container for web composition.ConfigureForWeb(); composition .ComposeUmbracoControllers(GetType().Assembly) .SetDefaultRenderMvcController(); // default controller for template views composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); composition.Register(Lifetime.Request); composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); composition.WithCollectionBuilder(); composition.RegisterUnique(); composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); //we need to eagerly scan controller types since they will need to be routed var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); composition.RegisterUnique(surfaceControllerTypes); //we need to eagerly scan controller types since they will need to be routed var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); composition.RegisterUnique(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others composition.WithCollectionBuilder() .Remove() .Remove() .Remove(); // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax composition.WithCollectionBuilder() .Append(); composition.WithCollectionBuilder() .Append() .Append() .Append(); composition.RegisterUnique(); composition.WithCollectionBuilder() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() .Append() .Append() //.Append() // disabled, this is an odd finder .Append() .Append(); composition.RegisterUnique(); composition.RegisterUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); // auto-register views composition.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router composition.RegisterUnique(); composition.Register(_ => Current.Configs.Settings().WebRouting); // register preview SignalR hub composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback composition.RegisterUnique(); // register known content apps composition.WithCollectionBuilder() .Append() .Append() .Append(); // register back office sections in the order we want them rendered composition.WithCollectionBuilder() .Append() .Append() .Append() .Append() .Append() .Append() .Append(); // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards composition.WithCollectionBuilder() .Add(composition.TypeLoader.GetTypes()); // register back office trees // the collection builder only accepts types inheriting from TreeControllerBase // and will filter out those that are not attributed with TreeAttribute composition.WithCollectionBuilder() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); } } }