diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Infrastructure/Compose/AuditEventsComponent.cs similarity index 98% rename from src/Umbraco.Web/Compose/AuditEventsComponent.cs rename to src/Umbraco.Infrastructure/Compose/AuditEventsComponent.cs index 4b5669a33f..c085db2496 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/AuditEventsComponent.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using System.Threading; +using Microsoft.Extensions.Options; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; @@ -23,13 +24,13 @@ namespace Umbraco.Core.Compose private readonly IIpResolver _ipResolver; private readonly GlobalSettings _globalSettings; - public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, GlobalSettings globalSettings) + public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IOptions globalSettings) { _auditService = auditService; _userService = userService; _entityService = entityService; _ipResolver = ipResolver; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void Initialize() diff --git a/src/Umbraco.Web/Compose/AuditEventsComposer.cs b/src/Umbraco.Infrastructure/Compose/AuditEventsComposer.cs similarity index 100% rename from src/Umbraco.Web/Compose/AuditEventsComposer.cs rename to src/Umbraco.Infrastructure/Compose/AuditEventsComposer.cs diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs deleted file mode 100644 index e5594a0778..0000000000 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ /dev/null @@ -1,348 +0,0 @@ -using System; -using System.Configuration; -using System.Data.SqlServerCe; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Web; -using Examine; -using Microsoft.Extensions.Logging; -using Moq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.Install; -using Umbraco.Core.Models; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Runtime; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services; -using Umbraco.Core.Sync; -using Umbraco.Tests.TestHelpers; -using Umbraco.Web; -using Umbraco.Web.Cache; -using Umbraco.Web.Macros; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; -using Umbraco.Web.Runtime; -using File = System.IO.File; -using Current = Umbraco.Web.Composing.Current; -using Umbraco.Tests.Common; -using Umbraco.Tests.Common.Composing; -using Umbraco.Core.Media; -using Umbraco.Tests.Common.Builders; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; - -namespace Umbraco.Tests.Runtimes -{ - [TestFixture] - public class StandaloneTests - { - [Test] - [Explicit("This test must be run manually")] - public void StandaloneTest() - { - IFactory factory = null; - - // clear - foreach (var file in Directory.GetFiles(Path.Combine(TestHelper.IOHelper.MapPath("~/App_Data")), "NuCache.*")) - File.Delete(file); - - // settings - // reset the current version to 0.0.0, clear connection strings - ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus] = ""; - // FIXME: we need a better management of settings here (and, true config files?) - - var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); - // create the very basic and essential things we need - var profiler = new LogProfiler(loggerFactory.CreateLogger()); - var profilingLogger = new ProfilingLogger(loggerFactory.CreateLogger("ProfilingLogger"), profiler); - var appCaches = AppCaches.Disabled; - var globalSettings = new GlobalSettings(); - var connectionStrings = new ConnectionStrings(); - var typeFinder = TestHelper.GetTypeFinder(); - var databaseFactory = new UmbracoDatabaseFactory(loggerFactory.CreateLogger(), loggerFactory, Options.Create(globalSettings), Options.Create(connectionStrings), new Lazy(() => factory.GetInstance()), TestHelper.DbProviderFactoryCreator); - var ioHelper = TestHelper.IOHelper; - var hostingEnvironment = Mock.Of(); - var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), loggerFactory.CreateLogger(), profilingLogger); - var mainDom = new SimpleMainDom(); - var umbracoVersion = TestHelper.GetUmbracoVersion(); - var backOfficeInfo = TestHelper.GetBackOfficeInfo(); - var runtimeState = new RuntimeState(globalSettings, umbracoVersion, databaseFactory, loggerFactory.CreateLogger()); - var variationContextAccessor = TestHelper.VariationContextAccessor; - - // create the register and the composition - var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); - composition.RegisterEssentials(loggerFactory.CreateLogger("Essentials"), loggerFactory, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); - - // create the core runtime and have it compose itself - var coreRuntime = new CoreRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, loggerFactory, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, AppCaches.NoCache); - - // determine actual runtime level - runtimeState.DetermineRuntimeLevel(); - Console.WriteLine(runtimeState.Level); - // going to be Install BUT we want to force components to be there (nucache etc) - runtimeState.Level = RuntimeLevel.Run; - - var composerTypes = typeLoader.GetTypes() // all of them - .Where(x => !x.FullName.StartsWith("Umbraco.Tests.")) // exclude test components - .Where(x => x != typeof(WebInitialComposer) && x != typeof(WebFinalComposer)); // exclude web runtime - var composers = new Composers(composition, composerTypes, Enumerable.Empty(), loggerFactory.CreateLogger(), profilingLogger); - composers.Compose(); - - // must registers stuff that WebRuntimeComponent would register otherwise - // FIXME: UmbracoContext creates a snapshot that it does not register with the accessor - // and so, we have to use the UmbracoContextPublishedSnapshotAccessor - // the UmbracoContext does not know about the accessor - // else that would be a catch-22 where they both know about each other? - //composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(Lifetime.Singleton); - composition.Register(_ => Mock.Of(), Lifetime.Singleton); - composition.RegisterUnique(f => new DistributedCache(f.GetInstance(), f.GetInstance())); - composition.Register(_ => Mock.Of(), Lifetime.Singleton); - composition.WithCollectionBuilder().Append(); - composition.RegisterUnique(); - composition.RegisterUnique(); - composition.RegisterUnique(); - composition.RegisterUnique(); - composition.RegisterUnique(_ => new MediaUrlProviderCollection(Enumerable.Empty())); - - // TODO: found these registration were necessary here as dependencies for ComponentCollection - // are not resolved. Need to check this if these explicit registrations are the best way to handle this. - var contentSettings = new ContentSettings(); - var coreDebugSettings = new CoreDebugSettings(); - var nuCacheSettings = new NuCacheSettings(); - var requestHandlerSettings = new RequestHandlerSettings(); - var userPasswordConfigurationSettings = new UserPasswordConfigurationSettings(); - var webRoutingSettings = new WebRoutingSettings(); - - composition.Register(x => Options.Create(globalSettings)); - composition.Register(x => Options.Create(contentSettings)); - composition.Register(x => Options.Create(coreDebugSettings)); - composition.Register(x => Options.Create(nuCacheSettings)); - composition.Register(x => Options.Create(requestHandlerSettings)); - composition.Register(x => Options.Create(userPasswordConfigurationSettings)); - composition.Register(x => Options.Create(webRoutingSettings)); - - // initialize some components only/individually - composition.WithCollectionBuilder() - .Clear() - .Append(); - - // configure - - // create and register the factory - Current.Factory = factory = composition.CreateFactory(); - - // instantiate and initialize components - var components = factory.GetInstance(); - - // do stuff - Console.WriteLine(runtimeState.Level); - - // install - if (true || runtimeState.Level == RuntimeLevel.Install) - { - var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var file = databaseFactory.Configured ? Path.Combine(path, "UmbracoNPocoTests.sdf") : Path.Combine(path, "Umbraco.sdf"); - if (File.Exists(file)) - File.Delete(file); - - // create the database file - // databaseBuilder.ConfigureEmbeddedDatabaseConnection() can do it too, - // but then it wants to write the connection string to web.config = bad - var connectionString = databaseFactory.Configured ? databaseFactory.ConnectionString : "Data Source=|DataDirectory|\\Umbraco.sdf;Flush Interval=1;"; - using (var engine = new SqlCeEngine(connectionString)) - { - engine.CreateDatabase(); - } - - //var databaseBuilder = factory.GetInstance(); - //databaseFactory.Configure(DatabaseBuilder.EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe); - //databaseBuilder.CreateDatabaseSchemaAndData(); - - if (!databaseFactory.Configured) - databaseFactory.Configure(DatabaseBuilder.EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe); - - var scopeProvider = factory.GetInstance(); - using (var scope = scopeProvider.CreateScope()) - { - var creator = new DatabaseSchemaCreator(scope.Database, loggerFactory.CreateLogger(), loggerFactory, umbracoVersion); - creator.InitializeDatabaseSchema(); - scope.Complete(); - } - } - - // done installing - runtimeState.Level = RuntimeLevel.Run; - - components.Initialize(); - - // instantiate to register events - // should be done by Initialize? - // should we invoke Initialize? - _ = factory.GetInstance(); - - // at that point, Umbraco can run! - // though, we probably still need to figure out what depends on HttpContext... - var contentService = factory.GetInstance(); - var content = contentService.GetById(1234); - Assert.IsNull(content); - - // create a document type and a document - var contentType = new ContentType(TestHelper.ShortStringHelper, -1) { Alias = "ctype", Name = "ctype" }; - factory.GetInstance().Save(contentType); - content = new Content("test", -1, contentType); - contentService.Save(content); - - // assert that it is possible to get the document back - content = contentService.GetById(content.Id); - Assert.IsNotNull(content); - Assert.AreEqual("test", content.Name); - - // need an UmbracoCOntext to access the cache - var umbracoContextFactory = factory.GetInstance(); - var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); - var umbracoContext = umbracoContextReference.UmbracoContext; - - // assert that there is no published document - var pcontent = umbracoContext.Content.GetById(content.Id); - Assert.IsNull(pcontent); - - // but a draft document - pcontent = umbracoContext.Content.GetById(true, content.Id); - Assert.IsNotNull(pcontent); - Assert.AreEqual("test", pcontent.Name(variationContextAccessor)); - Assert.IsTrue(pcontent.IsDraft()); - - // no published url - Assert.AreEqual("#", pcontent.Url()); - - // now publish the document + make some unpublished changes - contentService.SaveAndPublish(content); - content.Name = "testx"; - contentService.Save(content); - - // assert that snapshot has been updated and there is now a published document - pcontent = umbracoContext.Content.GetById(content.Id); - Assert.IsNotNull(pcontent); - Assert.AreEqual("test", pcontent.Name(variationContextAccessor)); - Assert.IsFalse(pcontent.IsDraft()); - - // but the url is the published one - no draft url - Assert.AreEqual("/test/", pcontent.Url()); - - // and also an updated draft document - pcontent = umbracoContext.Content.GetById(true, content.Id); - Assert.IsNotNull(pcontent); - Assert.AreEqual("testx", pcontent.Name(variationContextAccessor)); - Assert.IsTrue(pcontent.IsDraft()); - - // and the published document has a url - Assert.AreEqual("/test/", pcontent.Url()); - - umbracoContextReference.Dispose(); - mainDom.Stop(); - components.Terminate(); - - // exit! - } - - [Test] - [Explicit("This test must be run manually")] - public void ValidateComposition() - { - // this is almost what CoreRuntime does, without - // - managing MainDom - // - configuring for unhandled exceptions, assembly resolution, application root path - // - testing for database, and for upgrades (runtime level) - // - assigning the factory to Current.Factory - - // create the very basic and essential things we need - var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); - var profiler = Mock.Of(); - var profilingLogger = new ProfilingLogger(loggerFactory.CreateLogger("ProfilingLogger"), profiler); - var appCaches = AppCaches.Disabled; - var databaseFactory = Mock.Of(); - var typeFinder = TestHelper.GetTypeFinder(); - var ioHelper = TestHelper.IOHelper; - var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), loggerFactory.CreateLogger(), profilingLogger); - var runtimeState = Mock.Of(); - var hostingEnvironment = Mock.Of(); - var backOfficeInfo = TestHelper.GetBackOfficeInfo(); - Mock.Get(runtimeState).Setup(x => x.Level).Returns(RuntimeLevel.Run); - var mainDom = Mock.Of(); - Mock.Get(mainDom).Setup(x => x.IsMainDom).Returns(true); - - // create the register and the composition - var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); - var umbracoVersion = TestHelper.GetUmbracoVersion(); - composition.RegisterEssentials(loggerFactory.CreateLogger("RegisterEssentials"), loggerFactory, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); - - // create the core runtime and have it compose itself - var globalSettings = new GlobalSettings(); - var connectionStrings = new ConnectionStrings(); - - var coreRuntime = new CoreRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, loggerFactory, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, AppCaches.NoCache); - - // get the components - // all of them? - var composerTypes = typeLoader.GetTypes(); - // filtered - composerTypes = composerTypes - .Where(x => !x.FullName.StartsWith("Umbraco.Tests")); - // single? - //var componentTypes = new[] { typeof(CoreRuntimeComponent) }; - var composers = new Composers(composition, composerTypes, Enumerable.Empty(), loggerFactory.CreateLogger(), profilingLogger); - - // get components to compose themselves - composers.Compose(); - - // create the factory - var factory = composition.CreateFactory(); - - // at that point Umbraco is fully composed - // but nothing is initialized (no maindom, nothing - beware!) - // to actually *run* Umbraco standalone, better use a StandaloneRuntime - // that would inherit from CoreRuntime and ensure everything starts - - // get components to initialize themselves - //components.Initialize(factory); - - // and then, validate - var lightInjectContainer = (LightInject.ServiceContainer) factory.Concrete; - var results = lightInjectContainer.Validate().ToList(); - foreach (var resultGroup in results.GroupBy(x => x.Severity).OrderBy(x => x.Key)) - { - Console.WriteLine($"{resultGroup.Key}: {resultGroup.Count()}"); - } - - foreach (var resultGroup in results.GroupBy(x => x.Severity).OrderBy(x => x.Key)) - foreach (var result in resultGroup) - { - Console.WriteLine(); - Console.Write(result.ToText()); - } - - Assert.AreEqual(0, results.Count); - } - - - - - } -} diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs deleted file mode 100644 index da33685bdd..0000000000 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ /dev/null @@ -1,308 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using Microsoft.Extensions.Logging.Abstractions; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Web.Composing; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.Services.Implement; -using Umbraco.Tests.LegacyXmlPublishedCache; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Tests.Testing; - -namespace Umbraco.Tests.Services -{ - /// - /// Tests covering all methods in the ContentService class. - /// This is more of an integration test as it involves multiple layers - /// as well as configuration. - /// - [TestFixture] - [Apartment(ApartmentState.STA)] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - [NUnit.Framework.Explicit("These should not be run by the server, only directly as they are only benchmark tests")] - public class PerformanceTests : TestWithDatabaseBase - { - protected override string GetDbConnectionString() - { - return @"server=.\SQLEXPRESS;database=UmbTest;user id=sa;password=test"; - } - - protected override string GetDbProviderName() - { - return Constants.DbProviderNames.SqlServer; - } - - - /// - /// don't create anything, we're testing against our own server - /// - protected override void CreateSqlCeDatabase() - { - } - - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - - private static IProfilingLogger GetTestProfilingLogger() - { - var profiler = new TestProfiler(); - return new ProfilingLogger(new NullLogger(), profiler); - } - - [Test] - public void Get_All_Published_Content() - { - var result = PrimeDbWithLotsOfContent(); - var contentSvc = (ContentService) ServiceContext.ContentService; - - var countOfPublished = result.Count(x => x.Published); - var contentTypeId = result.First().ContentTypeId; - - var proflog = GetTestProfilingLogger(); - using (proflog.DebugDuration("Getting published content normally")) - { - //do this 10x! - for (var i = 0; i < 10; i++) - { - - var published = new List(); - //get all content items that are published - var rootContent = contentSvc.GetRootContent(); - foreach (var content in rootContent.Where(content => content.Published)) - { - published.Add(content); - published.AddRange(contentSvc.GetPublishedDescendants(content)); - } - Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); - } - - } - - using (proflog.DebugDuration("Getting published content optimized")) - { - - //do this 10x! - for (var i = 0; i < 10; i++) - { - - //get all content items that are published - var published = contentSvc.GetAllPublished(); - - Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); - } - } - } - - - [Test] - public void Truncate_Insert_Vs_Update_Insert() - { - var customObjectType = Guid.NewGuid(); - //chuck lots of data in the db - var nodes = PrimeDbWithLotsOfContentXmlRecords(customObjectType); - var proflog = GetTestProfilingLogger(); - - //now we need to test the difference between truncating all records and re-inserting them as we do now, - //vs updating them (which might result in checking if they exist for or listening on an exception). - using (proflog.DebugDuration("Starting truncate + normal insert test")) - using (var scope = ScopeProvider.CreateScope()) - { - //do this 10x! - for (var i = 0; i < 10; i++) - { - //clear all the xml entries - scope.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN - (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml - INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)"); - - //now we insert each record for the ones we've deleted like we do in the content service. - var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList(); - foreach (var xml in xmlItems) - { - var result = scope.Database.Insert(xml); - } - } - - scope.Complete(); - } - - //now, isntead of truncating, we'll attempt to update and if it doesn't work then we insert - using (proflog.DebugDuration("Starting update test")) - using (var scope = ScopeProvider.CreateScope()) - { - //do this 10x! - for (var i = 0; i < 10; i++) - { - //now we insert each record for the ones we've deleted like we do in the content service. - var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList(); - foreach (var xml in xmlItems) - { - var result = scope.Database.Update(xml); - } - } - - scope.Complete(); - } - - //now, test truncating but then do bulk insertion of records - using (proflog.DebugDuration("Starting truncate + bulk insert test in one transaction")) - using (var scope = ScopeProvider.CreateScope()) - { - //do this 10x! - for (var i = 0; i < 10; i++) - { - //now we insert each record for the ones we've deleted like we do in the content service. - var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList(); - - //clear all the xml entries - scope.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN - (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml - INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)"); - - - scope.Database.BulkInsertRecords(xmlItems); - } - - scope.Complete(); - } - } - - private IEnumerable PrimeDbWithLotsOfContent() - { - var contentType1 = MockedContentTypes.CreateSimpleContentType(); - contentType1.AllowedAsRoot = true; - ServiceContext.ContentTypeService.Save(contentType1); - contentType1.AllowedContentTypes = new List - { - new ContentTypeSort(new Lazy(() => contentType1.Id), 0, contentType1.Alias) - }; - var result = new List(); - ServiceContext.ContentTypeService.Save(contentType1); - IContent lastParent = MockedContent.CreateSimpleContent(contentType1); - lastParent.PublishCulture(CultureImpact.Invariant); - ServiceContext.ContentService.SaveAndPublish(lastParent); - result.Add(lastParent); - //create 20 deep - for (var i = 0; i < 20; i++) - { - //for each level, create 20 - IContent content = null; - for (var j = 1; j <= 10; j++) - { - content = MockedContent.CreateSimpleContent(contentType1, "Name" + j, lastParent); - //only publish evens - if (j % 2 == 0) - { - content.PublishCulture(CultureImpact.Invariant); - ServiceContext.ContentService.SaveAndPublish(content); - } - else - { - ServiceContext.ContentService.Save(content); - } - result.Add(content); - } - - //assign the last one as the next parent - lastParent = content; - } - return result; - } - - private IEnumerable PrimeDbWithLotsOfContentXmlRecords(Guid customObjectType) - { - var nodes = new List(); - for (var i = 1; i < 10000; i++) - { - nodes.Add(new NodeDto - { - Level = 1, - ParentId = -1, - NodeObjectType = customObjectType, - Text = i.ToString(CultureInfo.InvariantCulture), - UserId = -1, - CreateDate = DateTime.Now, - Trashed = false, - SortOrder = 0, - Path = "" - }); - } - - using (var scope = ScopeProvider.CreateScope()) - { - scope.Database.BulkInsertRecords(nodes); - - //re-get the nodes with ids - var sql = Current.SqlContext.Sql(); - sql.SelectAll().From().Where(x => x.NodeObjectType == customObjectType); - nodes = scope.Database.Fetch(sql); - - //create the cmsContent data, each with a new content type id (so we can query on it later if needed) - var contentTypeId = 0; - var cmsContentItems = nodes.Select(node => new ContentDto { NodeId = node.NodeId, ContentTypeId = contentTypeId++ }).ToList(); - scope.Database.BulkInsertRecords(cmsContentItems); - - //create the xml data - var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = TestXmlStructure }).ToList(); - scope.Database.BulkInsertRecords(xmlItems); - - scope.Complete(); - } - - return nodes; - } - - private const string TestXmlStructure = @" - 0 - Standard Site for Umbraco by Koiak - - - - Built by Creative Founds -

Web ApplicationsCreative Founds design and build first class software solutions that deliver big results. We provide ASP.NET web and mobile applications, Umbraco development service & technical consultancy.

-

www.creativefounds.co.uk

]]>
- Umbraco Development -

UmbracoUmbraco the the leading ASP.NET open source CMS, under pinning over 150,000 websites. Our Certified Developers are experts in developing high performance and feature rich websites.

]]>
- Contact Us -

Contact Us on TwitterWe'd love to hear how this package has helped you and how it can be improved. Get in touch on the project website or via twitter

]]>
- -
Standard Website MVC, Company Address, Glasgow, Postcode
- Copyright &copy; 2012 Your Company - http://www.umbraco.org - /media/1477/umbraco_logo.png - - - - - - - 2013-07-01T00:00:00 -
"; - - private const string UpdatedXmlStructure = @" - 0 - - - - Clients -

This is a standard content page.

-

Vestibulum malesuada aliquet ante, vitae ullamcorper felis faucibus vel. Vestibulum condimentum faucibus tellus porta ultrices. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

-

Cras at auctor orci. Praesent facilisis erat nec odio consequat at posuere ligula pretium. Nulla eget felis id nisl volutpat pellentesque. Ut id augue id ligula placerat rutrum a nec purus. Maecenas sed lectus ac mi pellentesque luctus quis sit amet turpis. Vestibulum adipiscing convallis vestibulum.

-

Duis condimentum lectus at orci placerat vitae imperdiet lorem cursus. Duis hendrerit porta lorem, non suscipit quam consectetur vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elit augue, tincidunt nec tincidunt id, elementum vel est.

]]>
- -
"; - - } -} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 24abe3f774..3694a782ab 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -165,7 +165,6 @@ - @@ -255,7 +254,6 @@ - diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index b87b5d0fbb..e684f7a945 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -32,6 +32,7 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.BackOffice.Controllers { + [DisableBrowserCache] //TODO Reintroduce //[UmbracoRequireHttps] //TODO Reintroduce [PluginController(Constants.Web.Mvc.BackOfficeArea)] public class BackOfficeController : UmbracoController diff --git a/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs index 5cc481c018..dad432198c 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs @@ -1,4 +1,7 @@ using Umbraco.Core.Composing; +using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Web.Common.Controllers; +using Umbraco.Web.Common.Install; using Umbraco.Web.Trees; // the namespace here is intentional - although defined in Umbraco.Web assembly, @@ -25,5 +28,25 @@ namespace Umbraco.Extensions #endregion + + /// + /// Registers Umbraco backoffice controllers. + /// + public static Composition ComposeUmbracoBackOfficeControllers(this Composition composition) + { + composition.RegisterControllers(new [] + { + typeof(BackOfficeController), + typeof(PreviewController), + typeof(AuthenticationController), + typeof(InstallController), + typeof(InstallApiController), + }); + + var umbracoAuthorizedApiControllers = composition.TypeLoader.GetTypes(); + composition.RegisterControllers(umbracoAuthorizedApiControllers); + + return composition; + } } } diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs index a1a671527a..6a6a896bae 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs @@ -4,9 +4,9 @@ namespace Umbraco.Extensions { public static class UmbracoBuilderExtensions { - public static void BuildWithAllBackOfficeComponents(this IUmbracoBuilder builder) + public static IUmbracoBuilder WithAllBackOfficeComponents(this IUmbracoBuilder builder) { - builder + return builder .WithConfiguration() .WithCore() .WithWebComponents() @@ -16,8 +16,7 @@ namespace Umbraco.Extensions .WithMiniProfiler() .WithMvcAndRazor() .WithWebServer() - .WithPreview() - .Build(); + .WithPreview(); } public static IUmbracoBuilder WithBackOffice(this IUmbracoBuilder builder) diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs index 005a0db36e..0f90afc34b 100644 --- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs +++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs @@ -50,6 +50,8 @@ namespace Umbraco.Web.BackOffice.Runtime composition.RegisterUnique(); composition.RegisterUnique(); + + composition.ComposeUmbracoBackOfficeControllers(); } } } diff --git a/src/Umbraco.Web.Common/Extensions/CompositionExtensions.cs b/src/Umbraco.Web.Common/Extensions/CompositionExtensions.cs new file mode 100644 index 0000000000..2ce003d226 --- /dev/null +++ b/src/Umbraco.Web.Common/Extensions/CompositionExtensions.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Core.Composing; +using Umbraco.Web.Common.Controllers; +using Umbraco.Web.Mvc; + +namespace Umbraco.Extensions +{ + public static class CompositionExtensions + { + public static void RegisterControllers(this Composition composition, IEnumerable controllerTypes) + { + foreach (var controllerType in controllerTypes) + composition.Register(controllerType, Lifetime.Request); + } + } +} diff --git a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs index 3c2da057f7..113f411c6f 100644 --- a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs +++ b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs @@ -56,7 +56,7 @@ namespace Umbraco.Web.Common.ModelBinders // If types already match, return var sourceType = source.GetType(); - if (sourceType.Inherits(modelType)) // includes == + if (sourceType. Inherits(modelType)) // includes == { bindingContext.Result = ModelBindingResult.Success(source); return Task.CompletedTask; diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index aa141b2624..b4ef7f59ec 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -33,7 +33,10 @@ namespace Umbraco.Web.UI.NetCore public void ConfigureServices(IServiceCollection services) { var umbracoBuilder = services.AddUmbraco(_env, _config); - umbracoBuilder.BuildWithAllBackOfficeComponents(); + umbracoBuilder + .WithAllBackOfficeComponents() + .WithAllWebsiteComponents() + .Build(); } diff --git a/src/Umbraco.Web.Website/Extensions/CompositionExtensions.cs b/src/Umbraco.Web.Website/Extensions/CompositionExtensions.cs new file mode 100644 index 0000000000..c832f2fac0 --- /dev/null +++ b/src/Umbraco.Web.Website/Extensions/CompositionExtensions.cs @@ -0,0 +1,39 @@ +using System.Linq; +using Umbraco.Core.Composing; +using Umbraco.Web.Common.Controllers; +using Umbraco.Web.Mvc; +using Umbraco.Web.Website.Controllers; + +namespace Umbraco.Extensions +{ + public static class CompositionExtensions + { + /// + /// Registers Umbraco website controllers. + /// + public static Composition ComposeWebsiteUmbracoControllers(this Composition composition) + { + composition.RegisterControllers(new [] + { + // typeof(UmbProfileController), //TODO introduce when migrated + // typeof(UmbLoginStatusController),//TODO introduce when migrated + // typeof(UmbRegisterController),//TODO introduce when migrated + // typeof(UmbLoginController),//TODO introduce when migrated + typeof(RenderMvcController), + + }); + + var umbracoWebAssembly = typeof(SurfaceController).Assembly; + + // scan and register every PluginController in everything (PluginController is IDiscoverable and IController) + var nonUmbracoWebPluginController = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); + composition.RegisterControllers(nonUmbracoWebPluginController); + + // can and register every IRenderMvcController in everything (IRenderMvcController is IDiscoverable) + var renderMvcControllers = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); + composition.RegisterControllers(renderMvcControllers); + + return composition; + } + } +} diff --git a/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs new file mode 100644 index 0000000000..8e56cd6dca --- /dev/null +++ b/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs @@ -0,0 +1,20 @@ +using Umbraco.Web.Common.Builder; + +namespace Umbraco.Extensions +{ + public static class UmbracoBuilderExtensions + { + public static IUmbracoBuilder WithAllWebsiteComponents(this IUmbracoBuilder builder) + { + builder + .WithUmbracoWebsite(); + + return builder; + } + + public static IUmbracoBuilder WithUmbracoWebsite(this IUmbracoBuilder builder) + => builder.AddWith(nameof(WithUmbracoWebsite), () => builder.Services.AddUmbracoWebsite()); + + + } +} diff --git a/src/Umbraco.Web.Website/Extensions/UmbracoWebstiteServiceCollectionExtensions.cs b/src/Umbraco.Web.Website/Extensions/UmbracoWebstiteServiceCollectionExtensions.cs new file mode 100644 index 0000000000..bdc9ee840c --- /dev/null +++ b/src/Umbraco.Web.Website/Extensions/UmbracoWebstiteServiceCollectionExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.Extensions.DependencyInjection; + +namespace Umbraco.Extensions +{ + public static class UmbracoWebstiteServiceCollectionExtensions + { + public static void AddUmbracoWebsite(this IServiceCollection services) + { + services.AddSingleton(); + } + } +} diff --git a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs new file mode 100644 index 0000000000..0e99875dc0 --- /dev/null +++ b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs @@ -0,0 +1,24 @@ +using Umbraco.Core.Composing; +using Umbraco.Extensions; +using Umbraco.Web.Common.Runtime; +using Umbraco.Web.Website.Controllers; + +namespace Umbraco.Web.Website.Runtime +{ + // web's initial composer composes after core's, and before all core composers + [ComposeBefore(typeof(ICoreComposer))] + [ComposeAfter(typeof(AspNetCoreComposer))] + public class WebsiteComposer : IComposer + { + public void Compose(Composition composition) + { + + composition + .ComposeWebsiteUmbracoControllers() + //.SetDefaultRenderMvcController()// default controller for template views + ; + + } + } +} + diff --git a/src/Umbraco.Web/Composing/CompositionExtensions/Controllers.cs b/src/Umbraco.Web/Composing/CompositionExtensions/Controllers.cs deleted file mode 100644 index 329c93360b..0000000000 --- a/src/Umbraco.Web/Composing/CompositionExtensions/Controllers.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Web.Http.Controllers; -using System.Web.Mvc; -using Umbraco.Core.Composing; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; - -namespace Umbraco.Web.Composing.CompositionExtensions -{ - internal static class Controllers - { - /// - /// Registers Umbraco controllers. - /// - public static Composition ComposeUmbracoControllers(this Composition composition, Assembly umbracoWebAssembly) - { - // notes - // - // We scan and auto-registers: - // - every IController and IHttpController that *we* have in Umbraco.Web - // - PluginController, RenderMvcController and UmbracoApiController in every assembly - // - // We do NOT scan: - // - any IController or IHttpController (anything not PluginController nor UmbracoApiController), outside of Umbraco.Web - // which means that users HAVE to explicitly register their own non-Umbraco controllers - // - // This is because we try to achieve a balance between "simple" and "fast. Scanning for PluginController or - // UmbracoApiController is fast-ish because they both are IDiscoverable. Scanning for IController or IHttpController - // is a full, non-cached scan = expensive, we do it only for 1 assembly. - // - // TODO: find a way to scan for IController *and* IHttpController in one single pass - // or, actually register them manually so don't require a full scan for these - // 5 are IController but not PluginController - // Umbraco.Web.Mvc.RenderMvcController - // Umbraco.Web.Install.Controllers.InstallController - // Umbraco.Web.Macros.PartialViewMacroController - // Umbraco.Web.Editors.PreviewController - // Umbraco.Web.Editors.BackOfficeController - // 9 are IHttpController but not UmbracoApiController - // Umbraco.Web.Controllers.UmbProfileController - // Umbraco.Web.Controllers.UmbLoginStatusController - // Umbraco.Web.Controllers.UmbRegisterController - // Umbraco.Web.Controllers.UmbLoginController - // Umbraco.Web.Mvc.RenderMvcController - // Umbraco.Web.Install.Controllers.InstallController - // Umbraco.Web.Macros.PartialViewMacroController - // Umbraco.Web.Editors.PreviewController - // Umbraco.Web.Editors.BackOfficeController - - // scan and register every IController in Umbraco.Web - var umbracoWebControllers = composition.TypeLoader.GetTypes(specificAssemblies: new[] { umbracoWebAssembly }); - //foreach (var controller in umbracoWebControllers.Where(x => !typeof(PluginController).IsAssignableFrom(x))) - // Current.Logger.Debug(typeof(LightInjectExtensions), "IController NOT PluginController: " + controller.FullName); - composition.RegisterControllers(umbracoWebControllers); - - // scan and register every PluginController in everything (PluginController is IDiscoverable and IController) - var nonUmbracoWebPluginController = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); - composition.RegisterControllers(nonUmbracoWebPluginController); - - // can and register every IRenderMvcController in everything (IRenderMvcController is IDiscoverable) - var renderMvcControllers = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); - composition.RegisterControllers(renderMvcControllers); - - // scan and register every IHttpController in Umbraco.Web - var umbracoWebHttpControllers = composition.TypeLoader.GetTypes(specificAssemblies: new[] { umbracoWebAssembly }); - //foreach (var controller in umbracoWebControllers.Where(x => !typeof(UmbracoApiController).IsAssignableFrom(x))) - // Current.Logger.Debug(typeof(LightInjectExtensions), "IHttpController NOT UmbracoApiController: " + controller.FullName); - composition.RegisterControllers(umbracoWebHttpControllers); - - // scan and register every UmbracoApiController in everything (UmbracoApiController is IDiscoverable and IHttpController) - var nonUmbracoWebApiControllers = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); - composition.RegisterControllers(nonUmbracoWebApiControllers); - - return composition; - } - - private static void RegisterControllers(this Composition composition, IEnumerable controllerTypes) - { - foreach (var controllerType in controllerTypes) - composition.Register(controllerType, Lifetime.Request); - } - } -} diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 0889a9c019..5a190a90a5 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -167,9 +167,6 @@ namespace Umbraco.Web.Composing internal static SurfaceControllerTypeCollection SurfaceControllerTypes => Factory.GetInstance(); - public static FilteredControllerFactoryCollection FilteredControllerFactories - => Factory.GetInstance(); - internal static IPublishedSnapshotService PublishedSnapshotService => Factory.GetInstance(); @@ -216,38 +213,12 @@ namespace Umbraco.Web.Composing public static IRuntimeState RuntimeState => Factory.GetInstance(); - public static TypeLoader TypeLoader => Factory.GetInstance(); - - public static UrlSegmentProviderCollection UrlSegmentProviders => Factory.GetInstance(); - public static CacheRefresherCollection CacheRefreshers => Factory.GetInstance(); - public static DataEditorCollection DataEditors => Factory.GetInstance(); - - public static DataValueReferenceFactoryCollection DataValueReferenceFactories => Factory.GetInstance(); - - public static PropertyEditorCollection PropertyEditors => Factory.GetInstance(); - - public static ParameterEditorCollection ParameterEditors => Factory.GetInstance(); - - internal static ManifestValueValidatorCollection ManifestValidators => Factory.GetInstance(); - - internal static IPackageActionRunner PackageActionRunner => Factory.GetInstance(); - - internal static PackageActionCollection PackageActions => Factory.GetInstance(); - - internal static PropertyValueConverterCollection PropertyValueConverters => Factory.GetInstance(); - internal static IPublishedModelFactory PublishedModelFactory => Factory.GetInstance(); public static IServerMessenger ServerMessenger => Factory.GetInstance(); - public static IServerRegistrar ServerRegistrar => Factory.GetInstance(); - - public static ICultureDictionaryFactory CultureDictionaryFactory => Factory.GetInstance(); - - public static IShortStringHelper ShortStringHelper => Factory.GetInstance(); - public static ILogger Logger => Factory.GetInstance>(); public static ILoggerFactory LoggerFactory => Factory.GetInstance(); @@ -264,10 +235,6 @@ namespace Umbraco.Web.Composing public static IScopeProvider ScopeProvider => Factory.GetInstance(); - public static IFileSystems FileSystems => Factory.GetInstance(); - - public static ISqlContext SqlContext => Factory.GetInstance(); - public static IPublishedContentTypeFactory PublishedContentTypeFactory => Factory.GetInstance(); public static IPublishedValueFallback PublishedValueFallback => Factory.GetInstance(); diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 85b7b68c35..906c8fb60d 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -28,21 +28,8 @@ namespace Umbraco.Web /// public static class WebCompositionExtensions { - #region Collection Builders - /// - /// Gets the filtered controller factories collection builder. - /// - /// The composition. - /// - public static FilteredControllerFactoryCollectionBuilder FilteredControllerFactory(this Composition composition) - => composition.WithCollectionBuilder(); - - - - #endregion - #region Uniques /// diff --git a/src/Umbraco.Web/Logging/WebProfiler.cs b/src/Umbraco.Web/Logging/WebProfiler.cs deleted file mode 100755 index 6f15be7ecd..0000000000 --- a/src/Umbraco.Web/Logging/WebProfiler.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Threading; -using System.Web; -using StackExchange.Profiling; -using StackExchange.Profiling.SqlFormatters; -using Umbraco.Core; -using Umbraco.Core.Logging; - -namespace Umbraco.Web.Logging -{ - /// - /// Implements by using the MiniProfiler framework. - /// - /// - /// Profiling only runs when the app is in debug mode, see WebRuntime for how this gets created - /// - internal class WebProfiler : IProfiler, IProfilerHtml - { - private const string BootRequestItemKey = "Umbraco.Core.Logging.WebProfiler__isBootRequest"; - private readonly WebProfilerProvider _provider; - private int _first; - - public WebProfiler() - { - // create our own provider, which can provide a profiler even during boot - _provider = new WebProfilerProvider(); - - //see https://miniprofiler.com/dotnet/AspDotNet - MiniProfiler.Configure(new MiniProfilerOptions - { - SqlFormatter = new SqlServerFormatter(), - StackMaxLength = 5000, - ProfilerProvider = _provider - }); - } - - public void UmbracoApplicationBeginRequest(object sender, EventArgs e) - { - // if this is the first request, notify our own provider that this request is the boot request - var first = Interlocked.Exchange(ref _first, 1) == 0; - if (first) - { - _provider.BeginBootRequest(); - ((HttpApplication) sender).Context.Items[BootRequestItemKey] = true; - // and no need to start anything, profiler is already there - } - // else start a profiler, the normal way - else if (ShouldProfile(sender)) - Start(); - } - - public void UmbracoApplicationEndRequest(object sender, EventArgs e) - { - // if this is the boot request, or if we should profile this request, stop - // (the boot request is always profiled, no matter what) - var isBootRequest = ((HttpApplication) sender).Context.Items[BootRequestItemKey] != null; - if (isBootRequest) - _provider.EndBootRequest(); - if (isBootRequest || ShouldProfile(sender)) - Stop(); - } - - private static bool ShouldProfile(object sender) - { - var request = TryGetRequest(sender); - if (request.Success == false) return false; - - if (request.Result.Url.IsClientSideRequest()) return false; - if (bool.TryParse(request.Result.QueryString["umbDebug"], out var umbDebug)) return umbDebug; - if (bool.TryParse(request.Result.Headers["X-UMB-DEBUG"], out var xUmbDebug)) return xUmbDebug; - if (bool.TryParse(request.Result.Cookies["UMB-DEBUG"]?.Value, out var cUmbDebug)) return cUmbDebug; - return false; - } - - /// - public string Render() - { - return MiniProfiler.Current.RenderIncludes(RenderPosition.Right).ToString(); - } - - /// - public IDisposable Step(string name) - { - return MiniProfiler.Current?.Step(name); - } - - /// - public void Start() - { - MiniProfiler.StartNew(); - } - - /// - public void Stop(bool discardResults = false) - { - MiniProfiler.Current?.Stop(discardResults); - } - - private static Attempt TryGetRequest(object sender) - { - if (sender is HttpRequest httpRequest) - return Attempt.Succeed(new HttpRequestWrapper(httpRequest)); - - var app = sender as HttpApplication; - if (app == null) return Attempt.Fail(); - - try - { - var req = app.Request; - return Attempt.Succeed(new HttpRequestWrapper(req)); - } - catch (HttpException ex) - { - return Attempt.Fail(ex); - } - } - } -} diff --git a/src/Umbraco.Web/Logging/WebProfilerComponent.cs b/src/Umbraco.Web/Logging/WebProfilerComponent.cs deleted file mode 100755 index f2ac5e532c..0000000000 --- a/src/Umbraco.Web/Logging/WebProfilerComponent.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web; -using Microsoft.Extensions.Logging; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging; - -namespace Umbraco.Web.Logging -{ - internal sealed class WebProfilerComponent : IComponent - { - private readonly WebProfiler _profiler; - private readonly bool _profile; - - public WebProfilerComponent(IProfiler profiler, ILogger logger) - { - _profile = true; - - // although registered in WebRuntime.Compose, ensure that we have not - // been replaced by another component, and we are still "the" profiler - _profiler = profiler as WebProfiler; - if (_profiler != null) return; - - // if VoidProfiler was registered, let it be known - if (profiler is VoidProfiler) - logger.LogInformation("Profiler is VoidProfiler, not profiling (must run debug mode to profile)."); - _profile = false; - } - - public void Initialize() - { - if (!_profile) return; - - // bind to ApplicationInit - ie execute the application initialization for *each* application - // it would be a mistake to try and bind to the current application events - UmbracoApplicationBase.ApplicationInit += InitializeApplication; - } - - public void Terminate() - { - UmbracoApplicationBase.ApplicationInit -= InitializeApplication; - } - - private void InitializeApplication(object sender, EventArgs args) - { - if (!(sender is HttpApplication app)) return; - - // NOTE: We do not unbind these events ... because you just can't do that for HttpApplication events, they will - // be removed when the app dies. - app.BeginRequest += BeginRequest; - app.EndRequest += EndRequest; - } - - private void BeginRequest(object s, EventArgs a) => _profiler.UmbracoApplicationBeginRequest(s, a); - - private void EndRequest(object s, EventArgs a) => _profiler.UmbracoApplicationEndRequest(s, a); - } -} diff --git a/src/Umbraco.Web/Logging/WebProfilerComposer.cs b/src/Umbraco.Web/Logging/WebProfilerComposer.cs deleted file mode 100644 index 283c519b44..0000000000 --- a/src/Umbraco.Web/Logging/WebProfilerComposer.cs +++ /dev/null @@ -1,7 +0,0 @@ - using Umbraco.Core.Composing; - -namespace Umbraco.Web.Logging -{ - internal class WebProfilerComposer : ComponentComposer, ICoreComposer - { } -} diff --git a/src/Umbraco.Web/Logging/WebProfilerProvider.cs b/src/Umbraco.Web/Logging/WebProfilerProvider.cs deleted file mode 100755 index dbb81cf232..0000000000 --- a/src/Umbraco.Web/Logging/WebProfilerProvider.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Threading; -using System.Web; -using StackExchange.Profiling; -using StackExchange.Profiling.Internal; - -namespace Umbraco.Web.Logging -{ - /// - /// This is a custom MiniProfiler WebRequestProfilerProvider (which is generally the default) that allows - /// us to profile items during app startup - before an HttpRequest is created - /// - /// - /// Once the boot phase is changed to BootPhase.BootRequest then the base class (default) provider will handle all - /// profiling data and this sub class no longer performs any logic. - /// - internal class WebProfilerProvider : AspNetRequestProvider - { - private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(); - private MiniProfiler _startupProfiler; - private int _first; - private volatile BootPhase _bootPhase; - - public WebProfilerProvider() - { - // booting... - _bootPhase = BootPhase.Boot; - } - - /// - /// Indicates the boot phase. - /// - private enum BootPhase - { - Boot = 0, // boot phase (before the 1st request even begins) - BootRequest = 1, // request boot phase (during the 1st request) - Booted = 2 // done booting - } - - public void BeginBootRequest() - { - _locker.EnterWriteLock(); - try - { - if (_bootPhase != BootPhase.Boot) - throw new InvalidOperationException("Invalid boot phase."); - _bootPhase = BootPhase.BootRequest; - - // assign the profiler to be the current MiniProfiler for the request - // is's already active, starting and all - HttpContext.Current.Items[":mini-profiler:"] = _startupProfiler; - } - finally - { - _locker.ExitWriteLock(); - } - } - - public void EndBootRequest() - { - _locker.EnterWriteLock(); - try - { - if (_bootPhase != BootPhase.BootRequest) - throw new InvalidOperationException("Invalid boot phase."); - _bootPhase = BootPhase.Booted; - - _startupProfiler = null; - } - finally - { - _locker.ExitWriteLock(); - } - } - - /// - /// Starts a new MiniProfiler. - /// - /// - /// This is called when WebProfiler calls MiniProfiler.Start() so, - /// - as a result of WebRuntime starting the WebProfiler, and - /// - assuming profiling is enabled, on every BeginRequest that should be profiled, - /// - except for the very first one which is the boot request. - /// - public override MiniProfiler Start(string profilerName, MiniProfilerBaseOptions options) - { - var first = Interlocked.Exchange(ref _first, 1) == 0; - if (first == false) return base.Start(profilerName, options); - - _startupProfiler = new MiniProfiler("StartupProfiler", options); - CurrentProfiler = _startupProfiler; - return _startupProfiler; - } - - /// - /// Gets the current profiler. - /// - /// - /// If the boot phase is not Booted, then this will return the startup profiler (this), otherwise - /// returns the base class - /// - public override MiniProfiler CurrentProfiler - { - get - { - // if not booting then just use base (fast) - // no lock, _bootPhase is volatile - if (_bootPhase == BootPhase.Booted) - return base.CurrentProfiler; - - // else - try - { - var current = base.CurrentProfiler; - return current ?? _startupProfiler; - } - catch - { - return _startupProfiler; - } - } - - } - } -} diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs deleted file mode 100644 index 93dc6a14d5..0000000000 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ /dev/null @@ -1,427 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Logging; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Macros; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Security; -using Umbraco.Core.Services; - -namespace Umbraco.Web.Macros -{ - internal class MacroRenderer : IMacroRenderer - { - private readonly IProfilingLogger _profilingLogger; - private readonly ILogger _logger; - private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly ContentSettings _contentSettings; - private readonly ILocalizedTextService _textService; - private readonly AppCaches _appCaches; - private readonly IMacroService _macroService; - private readonly IIOHelper _ioHelper; - private readonly ICookieManager _cookieManager; - private readonly IMemberUserKeyProvider _memberUserKeyProvider; - private readonly ISessionManager _sessionManager; - private readonly IRequestAccessor _requestAccessor; - private readonly IHttpContextAccessor _httpContextAccessor; - - - public MacroRenderer( - IProfilingLogger profilingLogger , - ILogger logger, - IUmbracoContextAccessor umbracoContextAccessor, - IOptions contentSettings, - ILocalizedTextService textService, - AppCaches appCaches, - IMacroService macroService, - IIOHelper ioHelper, - ICookieManager cookieManager, - IMemberUserKeyProvider memberUserKeyProvider, - ISessionManager sessionManager, - IRequestAccessor requestAccessor, - IHttpContextAccessor httpContextAccessor) - { - _profilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger )); - _logger = logger; - _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); - _textService = textService; - _appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); - _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); - _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _cookieManager = cookieManager; - _memberUserKeyProvider = memberUserKeyProvider; - _sessionManager = sessionManager; - _requestAccessor = requestAccessor; - _httpContextAccessor = httpContextAccessor; - } - - #region MacroContent cache - - // gets this macro content cache identifier - private string GetContentCacheIdentifier(MacroModel model, int pageId, string cultureName) - { - var id = new StringBuilder(); - - var alias = model.Alias; - id.AppendFormat("{0}-", alias); - //always add current culture to the key to allow variants to have different cache results - if (!string.IsNullOrEmpty(cultureName)) - { - // are there any unusual culture formats we'd need to handle? - id.AppendFormat("{0}-", cultureName); - } - - if (model.CacheByPage) - id.AppendFormat("{0}-", pageId); - - if (model.CacheByMember) - { - object key = 0; - - if (_umbracoContextAccessor.UmbracoContext.Security.IsAuthenticated()) - { - key = _memberUserKeyProvider.GetMemberProviderUserKey() ?? 0; - } - - id.AppendFormat("m{0}-", key); - } - - foreach (var value in model.Properties.Select(x => x.Value)) - id.AppendFormat("{0}-", value.Length <= 255 ? value : value.Substring(0, 255)); - - return id.ToString(); - } - - // gets this macro content from the cache - // ensuring that it is appropriate to use the cache - private MacroContent GetMacroContentFromCache(MacroModel model) - { - // only if cache is enabled - if (_umbracoContextAccessor.UmbracoContext.InPreviewMode || model.CacheDuration <= 0) return null; - - var cache = _appCaches.RuntimeCache; - var macroContent = cache.GetCacheItem(CacheKeys.MacroContentCacheKey + model.CacheIdentifier); - - if (macroContent == null) return null; - - _logger.LogDebug("Macro content loaded from cache '{MacroCacheId}'", model.CacheIdentifier); - - // ensure that the source has not changed - // note: does not handle dependencies, and never has - var macroSource = GetMacroFile(model); // null if macro is not file-based - if (macroSource != null) - { - if (macroSource.Exists == false) - { - _logger.LogDebug("Macro source does not exist anymore, ignore cache."); - return null; - } - - if (macroContent.Date < macroSource.LastWriteTime) - { - _logger.LogDebug("Macro source has changed, ignore cache."); - return null; - } - } - - return macroContent; - } - - // stores macro content into the cache - private void AddMacroContentToCache(MacroModel model, MacroContent macroContent) - { - // only if cache is enabled - if (_umbracoContextAccessor.UmbracoContext.InPreviewMode || model.CacheDuration <= 0) return; - - // just make sure... - if (macroContent == null) return; - - // do not cache if it should cache by member and there's not member - if (model.CacheByMember) - { - var key = _memberUserKeyProvider.GetMemberProviderUserKey(); - if (key is null) return; - } - - // remember when we cache the content - macroContent.Date = DateTime.Now; - - var cache = _appCaches.RuntimeCache; - cache.Insert( - CacheKeys.MacroContentCacheKey + model.CacheIdentifier, - () => macroContent, - new TimeSpan(0, 0, model.CacheDuration) - ); - - _logger.LogDebug("Macro content saved to cache '{MacroCacheId}'", model.CacheIdentifier); - } - - // gets the macro source file name - // null if the macro is not file-based, or not supported - internal static string GetMacroFileName(MacroModel model) - { - string filename = model.MacroSource; // partial views are saved with their full virtual path - - return string.IsNullOrEmpty(filename) ? null : filename; - } - - // gets the macro source file - // null if macro is not file-based - private FileInfo GetMacroFile(MacroModel model) - { - var filename = GetMacroFileName(model); - if (filename == null) return null; - - var mapped = _ioHelper.MapPath(filename); - if (mapped == null) return null; - - var file = new FileInfo(mapped); - return file.Exists ? file : null; - } - - // updates the model properties values according to the attributes - private static void UpdateMacroModelProperties(MacroModel model, IDictionary macroParams) - { - foreach (var prop in model.Properties) - { - var key = prop.Key.ToLowerInvariant(); - prop.Value = macroParams != null && macroParams.ContainsKey(key) - ? macroParams[key]?.ToString() ?? string.Empty - : string.Empty; - } - } - #endregion - - #region Render/Execute - - public MacroContent Render(string macroAlias, IPublishedContent content, IDictionary macroParams) - { - var m = _appCaches.RuntimeCache.GetCacheItem(CacheKeys.MacroFromAliasCacheKey + macroAlias, () => _macroService.GetByAlias(macroAlias)); - - if (m == null) - throw new InvalidOperationException("No macro found by alias " + macroAlias); - - var macro = new MacroModel(m); - - UpdateMacroModelProperties(macro, macroParams); - return Render(macro, content); - } - - private MacroContent Render(MacroModel macro, IPublishedContent content) - { - if (content == null) throw new ArgumentNullException(nameof(content)); - - var macroInfo = $"Render Macro: {macro.Name}, cache: {macro.CacheDuration}"; - using (_profilingLogger.DebugDuration(macroInfo, "Rendered Macro.")) - { - // parse macro parameters ie replace the special [#key], [$key], etc. syntaxes - foreach (var prop in macro.Properties) - prop.Value = ParseAttribute(prop.Value); - - var cultureName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; - macro.CacheIdentifier = GetContentCacheIdentifier(macro, content.Id, cultureName); - - // get the macro from cache if it is there - var macroContent = GetMacroContentFromCache(macro); - - // macroContent.IsEmpty may be true, meaning the macro produces no output, - // but still can be cached because its execution did not trigger any error. - // so we need to actually render, only if macroContent is null - if (macroContent != null) - return macroContent; - - // this will take care of errors - // it may throw, if we actually want to throw, so better not - // catch anything here and let the exception be thrown - var attempt = ExecuteMacroOfType(macro, content); - - // by convention ExecuteMacroByType must either throw or return a result - // just check to avoid internal errors - macroContent = attempt.Result; - if (macroContent == null) - throw new Exception("Internal error, ExecuteMacroOfType returned no content."); - - // add to cache if render is successful - // content may be empty but that's not an issue - if (attempt.Success) - { - // write to cache (if appropriate) - AddMacroContentToCache(macro, macroContent); - } - - return macroContent; - } - } - - /// - /// Executes a macro of a given type. - /// - private Attempt ExecuteMacroWithErrorWrapper(MacroModel macro, string msgIn, string msgOut, Func getMacroContent, Func msgErr) - { - using (_profilingLogger.DebugDuration(msgIn, msgOut)) - { - return ExecuteProfileMacroWithErrorWrapper(macro, msgIn, getMacroContent, msgErr); - } - } - - /// - /// Executes a macro of a given type. - /// - private Attempt ExecuteProfileMacroWithErrorWrapper(MacroModel macro, string msgIn, Func getMacroContent, Func msgErr) - { - try - { - return Attempt.Succeed(getMacroContent()); - } - catch (Exception e) - { - _logger.LogWarning(e, "Failed {MsgIn}", msgIn); - - var macroErrorEventArgs = new MacroErrorEventArgs - { - Name = macro.Name, - Alias = macro.Alias, - MacroSource = macro.MacroSource, - Exception = e, - Behaviour = _contentSettings.MacroErrors - }; - - switch (macroErrorEventArgs.Behaviour) - { - case MacroErrorBehaviour.Inline: - // do not throw, eat the exception, display the trace error message - return Attempt.Fail(new MacroContent { Text = msgErr() }, e); - case MacroErrorBehaviour.Silent: - // do not throw, eat the exception, do not display anything - return Attempt.Fail(new MacroContent { Text = string.Empty }, e); - case MacroErrorBehaviour.Content: - // do not throw, eat the exception, display the custom content - return Attempt.Fail(new MacroContent { Text = macroErrorEventArgs.Html ?? string.Empty }, e); - //case MacroErrorBehaviour.Throw: - default: - // see http://issues.umbraco.org/issue/U4-497 at the end - // throw the original exception - throw; - } - } - } - - /// - /// Executes a macro. - /// - /// Returns an attempt that is successful if the macro ran successfully. If the macro failed - /// to run properly, the attempt fails, though it may contain a content. But for instance that content - /// should not be cached. In that case the attempt may also contain an exception. - private Attempt ExecuteMacroOfType(MacroModel model, IPublishedContent content) - { - if (model == null) throw new ArgumentNullException(nameof(model)); - - // ensure that we are running against a published node (ie available in XML) - // that may not be the case if the macro is embedded in a RTE of an unpublished document - - if (content == null) - return Attempt.Fail(new MacroContent { Text = "[macro failed (no content)]" }); - - var textService = _textService; - - return ExecuteMacroWithErrorWrapper(model, - $"Executing PartialView: MacroSource=\"{model.MacroSource}\".", - "Executed PartialView.", - () => ExecutePartialView(model, content), - () => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); - } - - - #endregion - - #region Execute engines - - /// - /// Renders a PartialView Macro. - /// - /// The text output of the macro execution. - private MacroContent ExecutePartialView(MacroModel macro, IPublishedContent content) - { - var engine = new PartialViewMacroEngine(_umbracoContextAccessor, _httpContextAccessor, _ioHelper); - return engine.Execute(macro, content); - } - - #endregion - - #region Execution helpers - - // parses attribute value looking for [@requestKey], [%sessionKey] - // supports fallbacks eg "[@requestKey],[%sessionKey],1234" - private string ParseAttribute(string attributeValue) - { - // check for potential querystring/cookie variables - attributeValue = attributeValue.Trim(); - if (attributeValue.StartsWith("[") == false) - return attributeValue; - - var tokens = attributeValue.Split(',').Select(x => x.Trim()).ToArray(); - - // ensure we only process valid input ie each token must be [?x] and not eg a json array - // like [1,2,3] which we don't want to parse - however the last one can be a literal, so - // don't check on the last one which can be just anything - check all previous tokens - - char[] validTypes = { '@', '%' }; - if (tokens.Take(tokens.Length - 1).Any(x => - x.Length < 4 // ie "[?x]".Length - too short - || x[0] != '[' // starts with [ - || x[x.Length - 1] != ']' // ends with ] - || validTypes.Contains(x[1]) == false)) - { - return attributeValue; - } - - foreach (var token in tokens) - { - var isToken = token.Length > 4 && token[0] == '[' && token[token.Length - 1] == ']' && validTypes.Contains(token[1]); - - if (isToken == false) - { - // anything that is not a token is a value, use it - attributeValue = token; - break; - } - - var type = token[1]; - var name = token.Substring(2, token.Length - 3); - - switch (type) - { - case '@': - attributeValue = _requestAccessor.GetRequestValue(name); - break; - case '%': - attributeValue = _sessionManager.GetSessionValue(name); - if (string.IsNullOrEmpty(attributeValue)) - attributeValue = _cookieManager.GetCookieValue(name); - break; - } - - attributeValue = attributeValue?.Trim(); - if (string.IsNullOrEmpty(attributeValue) == false) - break; // got a value, use it - } - - return attributeValue; - } - - #endregion - - } - -} diff --git a/src/Umbraco.Web/Macros/PartialViewMacroController.cs b/src/Umbraco.Web/Macros/PartialViewMacroController.cs deleted file mode 100644 index 21d7b3292c..0000000000 --- a/src/Umbraco.Web/Macros/PartialViewMacroController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Web.Mvc; -using Umbraco.Web.Models; -using Umbraco.Web.Mvc; -using System.Linq; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Web.Macros -{ - /// - /// Controller to render macro content for Partial View Macros - /// - [MergeParentContextViewData] - [HideFromTypeFinder] // explicitly used: do *not* find and register it! - internal class PartialViewMacroController : Controller - { - private readonly MacroModel _macro; - private readonly IPublishedContent _content; - - public PartialViewMacroController(MacroModel macro, IPublishedContent content) - { - _macro = macro; - _content = content; - } - - /// - /// Child action to render a macro - /// - /// - [ChildActionOnly] - public PartialViewResult Index() - { - var model = new PartialViewMacroModel( - _content, - _macro.Id, - _macro.Alias, - _macro.Name, - _macro.Properties.ToDictionary(x => x.Key, x => (object)x.Value)); - return PartialView(_macro.MacroSource, model); - } - } -} diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs deleted file mode 100644 index 0773bc31ca..0000000000 --- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; -using System.Web.WebPages; -using Umbraco.Web.Mvc; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Macros -{ - /// - /// A macro engine using MVC Partial Views to execute. - /// - public class PartialViewMacroEngine - { - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IIOHelper _ioHelper; - private readonly Func _getUmbracoContext; - - public PartialViewMacroEngine(IUmbracoContextAccessor umbracoContextAccessor, IHttpContextAccessor httpContextAccessor, IIOHelper ioHelper) - { - _httpContextAccessor = httpContextAccessor; - _ioHelper = ioHelper; - - _getUmbracoContext = () => - { - var context = umbracoContextAccessor.UmbracoContext; - if (context == null) - throw new InvalidOperationException($"The {GetType()} cannot execute with a null UmbracoContext.Current reference."); - return context; - }; - } - - public bool Validate(string code, string tempFileName, IPublishedContent currentPage, out string errorMessage) - { - var temp = GetVirtualPathFromPhysicalPath(tempFileName); - try - { - CompileAndInstantiate(temp); - } - catch (Exception exception) - { - errorMessage = exception.Message; - return false; - } - errorMessage = string.Empty; - return true; - } - - public MacroContent Execute(MacroModel macro, IPublishedContent content) - { - if (macro == null) throw new ArgumentNullException(nameof(macro)); - if (content == null) throw new ArgumentNullException(nameof(content)); - if (macro.MacroSource.IsNullOrWhiteSpace()) throw new ArgumentException("The MacroSource property of the macro object cannot be null or empty"); - - var httpContext = _httpContextAccessor.GetRequiredHttpContext(); - var umbCtx = _getUmbracoContext(); - var routeVals = new RouteData(); - routeVals.Values.Add("controller", "PartialViewMacro"); - routeVals.Values.Add("action", "Index"); - routeVals.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); //required for UmbracoViewPage - - //lets render this controller as a child action - var viewContext = new ViewContext { ViewData = new ViewDataDictionary() }; - //try and extract the current view context from the route values, this would be set in the UmbracoViewPage or in - // the UmbracoPageResult if POSTing to an MVC controller but rendering in Webforms - if (httpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Mvc.Constants.DataTokenCurrentViewContext)) - { - viewContext = (ViewContext)httpContext.Request.RequestContext.RouteData.DataTokens[Mvc.Constants.DataTokenCurrentViewContext]; - } - routeVals.DataTokens.Add("ParentActionViewContext", viewContext); - - var request = new RequestContext(httpContext, routeVals); - - string output = String.Empty; - - using (var controller = new PartialViewMacroController(macro, content)) - { - controller.ViewData = viewContext.ViewData; - - controller.ControllerContext = new ControllerContext(request, controller); - - //call the action to render - var result = controller.Index(); - output = controller.RenderViewResultAsString(result); - } - - return new MacroContent { Text = output }; - } - - private string GetVirtualPathFromPhysicalPath(string physicalPath) - { - var rootpath = _ioHelper.MapPath("~/"); - physicalPath = physicalPath.Replace(rootpath, ""); - physicalPath = physicalPath.Replace("\\", "/"); - return "~/" + physicalPath; - } - - private static PartialViewMacroPage CompileAndInstantiate(string virtualPath) - { - //Compile Razor - We Will Leave This To ASP.NET Compilation Engine & ASP.NET WebPages - //Security in medium trust is strict around here, so we can only pass a virtual file path - //ASP.NET Compilation Engine caches returned types - //Changed From BuildManager As Other Properties Are Attached Like Context Path/ - var webPageBase = WebPageBase.CreateInstanceFromVirtualPath(virtualPath); - var webPage = webPageBase as PartialViewMacroPage; - if (webPage == null) - throw new InvalidCastException("All Partial View Macro views must inherit from " + typeof(PartialViewMacroPage).FullName); - return webPage; - } - - } - -} diff --git a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs deleted file mode 100644 index 914e4bbb70..0000000000 --- a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Mvc -{ - public class ContainerControllerFactory : DefaultControllerFactory - { - private readonly Lazy _factory; - - public ContainerControllerFactory(Lazy factory) - { - _factory = factory; - } - - protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) - { - try - { - return (IController) _factory.Value.GetInstance(controllerType); - } - catch (Exception e) - { - throw new Exception($"Failed to create an instance of controller type {controllerType.FullName} (see inner exception).", e); - } - } - - public override void ReleaseController(IController controller) - { - _factory.Value.Release(controller); - } - } -} diff --git a/src/Umbraco.Web/Mvc/ContentModelBinder.cs b/src/Umbraco.Web/Mvc/ContentModelBinder.cs deleted file mode 100644 index 376ce737b4..0000000000 --- a/src/Umbraco.Web/Mvc/ContentModelBinder.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System; -using System.Text; -using System.Web; -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; -using Umbraco.Web.Models; - -namespace Umbraco.Web.Mvc -{ - /// - /// Maps view models, supporting mapping to and from any IPublishedContent or IContentModel. - /// - /// Migrated to .NET Core - public class ContentModelBinder : DefaultModelBinder, IModelBinderProvider - { - // use Instance - private ContentModelBinder() { } - - public static ContentModelBinder Instance = new ContentModelBinder(); - - /// - /// Binds the model to a value by using the specified controller context and binding context. - /// - /// - /// The bound value. - /// - /// The controller context.The binding context. - public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) - { - object model; - if (controllerContext.RouteData.DataTokens.TryGetValue(Core.Constants.Web.UmbracoDataToken, out model) == false) - return null; - - // this model binder deals with IContentModel and IPublishedContent by extracting the model from the route's - // datatokens. This data token is set in 2 places: RenderRouteHandler, UmbracoVirtualNodeRouteHandler - // and both always set the model to an instance of `ContentMOdel`. So if this isn't an instance of IContentModel then - // we need to let the DefaultModelBinder deal with the logic. - var contentModel = model as IContentModel; - if (contentModel == null) - { - model = base.BindModel(controllerContext, bindingContext); - if (model == null) return null; - } - - //if for any reason the model is not either IContentModel or IPublishedContent, then we return since those are the only - // types this binder is dealing with. - if ((model is IContentModel) == false && (model is IPublishedContent) == false) return null; - - return BindModel(model, bindingContext.ModelType); - } - - // source is the model that we have - // modelType is the type of the model that we need to bind to - // - // create a model object of the modelType by mapping: - // { ContentModel, ContentModel, IPublishedContent } - // to - // { ContentModel, ContentModel, IPublishedContent } - // - public static object BindModel(object source, Type modelType) - { - // null model, return - if (source == null) return null; - - // if types already match, return - var sourceType = source.GetType(); - if (sourceType.Inherits(modelType)) // includes == - return source; - - // try to grab the content - var sourceContent = source as IPublishedContent; // check if what we have is an IPublishedContent - if (sourceContent == null && sourceType.Implements()) - { - // else check if it's an IContentModel, and get the content - sourceContent = ((IContentModel)source).Content; - } - if (sourceContent == null) - { - // else check if we can convert it to a content - var attempt1 = source.TryConvertTo(); - if (attempt1.Success) sourceContent = attempt1.Result; - } - - // if we have a content - if (sourceContent != null) - { - // if model is IPublishedContent, check content type and return - if (modelType.Implements()) - { - if ((sourceContent.GetType().Inherits(modelType)) == false) - ThrowModelBindingException(true, false, sourceContent.GetType(), modelType); - return sourceContent; - } - - // if model is ContentModel, create and return - if (modelType == typeof(ContentModel)) - { - return new ContentModel(sourceContent); - } - - // if model is ContentModel, check content type, then create and return - if (modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(ContentModel<>)) - { - var targetContentType = modelType.GetGenericArguments()[0]; - if ((sourceContent.GetType().Inherits(targetContentType)) == false) - ThrowModelBindingException(true, true, sourceContent.GetType(), targetContentType); - return Activator.CreateInstance(modelType, sourceContent); - } - } - - // last chance : try to convert - var attempt2 = source.TryConvertTo(modelType); - if (attempt2.Success) return attempt2.Result; - - // fail - ThrowModelBindingException(false, false, sourceType, modelType); - return null; - } - - private static void ThrowModelBindingException(bool sourceContent, bool modelContent, Type sourceType, Type modelType) - { - var msg = new StringBuilder(); - - // prepare message - msg.Append("Cannot bind source"); - if (sourceContent) msg.Append(" content"); - msg.Append(" type "); - msg.Append(sourceType.FullName); - msg.Append(" to model"); - if (modelContent) msg.Append(" content"); - msg.Append(" type "); - msg.Append(modelType.FullName); - msg.Append("."); - - // raise event, to give model factories a chance at reporting - // the error with more details, and optionally request that - // the application restarts. - - var args = new ModelBindingArgs(sourceType, modelType, msg); - ModelBindingException?.Invoke(Instance, args); - - // TODO: with all of the tests I've done i don't think restarting the app here is required anymore, - // when I don't have this code enabled and i get a model binding error and just refresh, it fixes itself. - // We'll leave this for now though. - if (args.Restart) - { - msg.Append(" The application is restarting now."); - - var context = HttpContext.Current; - if (context == null) - { - AppDomain.Unload(AppDomain.CurrentDomain); - } - else - { - Current.UmbracoApplicationLifetime.Restart(); - } - - - } - - throw new ModelBindingException(msg.ToString()); - } - - public IModelBinder GetBinder(Type modelType) - { - // can bind to ContentModel (exact type match) - if (modelType == typeof(ContentModel)) return this; - - // can bind to ContentModel (exact generic type match) - if (modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(ContentModel<>)) return this; - - // can bind to TContent where TContent : IPublishedContent (any IPublishedContent implementation) - if (typeof(IPublishedContent).IsAssignableFrom(modelType)) return this; - return null; - } - - /// - /// Contains event data for the event. - /// - public class ModelBindingArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message) - { - SourceType = sourceType; - ModelType = modelType; - Message = message; - } - - /// - /// Gets the type of the source object. - /// - public Type SourceType { get; set; } - - /// - /// Gets the type of the view model. - /// - public Type ModelType { get; set; } - - /// - /// Gets the message string builder. - /// - /// Handlers of the event can append text to the message. - public StringBuilder Message { get; } - - /// - /// Gets or sets a value indicating whether the application should restart. - /// - public bool Restart { get; set; } - } - - /// - /// Occurs on model binding exceptions. - /// - public static event EventHandler ModelBindingException; - } -} diff --git a/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs b/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs index eb39cb8faa..a69b09efe0 100644 --- a/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs +++ b/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs @@ -20,8 +20,10 @@ namespace Umbraco.Web.Mvc /// internal static Type GetControllerTypeInternal(this IControllerFactory factory, RequestContext requestContext, string controllerName) { - if (factory is MasterControllerFactory controllerFactory) - return controllerFactory.GetControllerTypeInternal(requestContext, controllerName); + + //TODO Reintroduce for netcore + // if (factory is MasterControllerFactory controllerFactory) + // return controllerFactory.GetControllerTypeInternal(requestContext, controllerName); //we have no choice but to instantiate the controller var instance = factory.CreateController(requestContext, controllerName); diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollection.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollection.cs deleted file mode 100644 index 1c2d140379..0000000000 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollection.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Mvc -{ - public class FilteredControllerFactoryCollection : BuilderCollectionBase - { - public FilteredControllerFactoryCollection(IEnumerable items) - : base(items) - { } - } -} diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs deleted file mode 100644 index 2c4182beac..0000000000 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Mvc -{ - public class FilteredControllerFactoryCollectionBuilder : OrderedCollectionBuilderBase - { - protected override FilteredControllerFactoryCollectionBuilder This => this; - } -} diff --git a/src/Umbraco.Web/Mvc/IFilteredControllerFactory.cs b/src/Umbraco.Web/Mvc/IFilteredControllerFactory.cs deleted file mode 100644 index a2cc53a104..0000000000 --- a/src/Umbraco.Web/Mvc/IFilteredControllerFactory.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Linq; -using System.Web.Mvc; -using System.Web.Routing; - -namespace Umbraco.Web.Mvc -{ - - public interface IFilteredControllerFactory : IControllerFactory - { - /// - /// Determines whether this instance can handle the specified request. - /// - /// The request. - /// true if this instance can handle the specified request; otherwise, false. - /// - bool CanHandle(RequestContext request); - - } -} diff --git a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs deleted file mode 100644 index cfc931fc71..0000000000 --- a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Linq; -using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core.Composing; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - /// - /// A controller factory which uses an internal list of in order to invoke - /// different controller factories dependent upon their implementation of for the current - /// request. Allows circumvention of MVC3's singly registered IControllerFactory. - /// - /// - internal class MasterControllerFactory : ContainerControllerFactory - { - private readonly Func _factoriesAccessor; - private FilteredControllerFactoryCollection _factories; - - /// - /// Initializes a new instance of the with a factories accessor. - /// - /// The factories accessor. - public MasterControllerFactory(Func factoriesAccessor) - : base(new Lazy(() => Current.Factory)) - { - // note - // because the MasterControllerFactory needs to be ctored to be assigned to - // ControllerBuilder.Current when setting up Mvc and WebApi, it cannot be ctored by - // the IoC container - and yet we don't want that ctor to resolve the factories - // as that happen before everything is configured - so, passing a factories - // accessor function. - - _factoriesAccessor = factoriesAccessor; - } - - private IFilteredControllerFactory FactoryForRequest(RequestContext context) - { - if (_factories == null) _factories = _factoriesAccessor(); - return _factories.FirstOrDefault(x => x.CanHandle(context)); - } - - /// - /// Creates the specified controller by using the specified request context. - /// - /// The context of the HTTP request, which includes the HTTP context and route data. - /// The name of the controller. - /// The controller. - /// The parameter is null. - /// - /// The parameter is null or empty. - /// - public override IController CreateController(RequestContext requestContext, string controllerName) - { - var factory = FactoryForRequest(requestContext); - return factory != null - ? factory.CreateController(requestContext, controllerName) - : base.CreateController(requestContext, controllerName); - } - - /// - /// Retrieves the controller type for the specified name and request context. - /// - /// - /// - /// The controller type. - /// - /// The context of the HTTP request, which includes the HTTP context and route data. - /// The name of the controller. - internal Type GetControllerTypeInternal(RequestContext requestContext, string controllerName) - { - var factory = FactoryForRequest(requestContext); - if (factory != null) - { - //check to see if the factory is of type UmbracoControllerFactory which exposes the GetControllerType method so we don't have to create - // an instance of the controller to figure out what it is. This is a work around for not having a breaking change for: - // http://issues.umbraco.org/issue/U4-1726 - - if (factory is UmbracoControllerFactory umbFactory) - return umbFactory.GetControllerType(requestContext, controllerName); - - //we have no choice but to instantiate the controller - var instance = factory.CreateController(requestContext, controllerName); - var controllerType = instance?.GetType(); - factory.ReleaseController(instance); - - return controllerType; - } - - return GetControllerType(requestContext, controllerName); - } - - /// - /// Releases the specified controller. - /// - /// The controller to release. - /// - public override void ReleaseController(IController icontroller) - { - var released = false; - - if (icontroller is Controller controller) - { - var requestContext = controller.ControllerContext.RequestContext; - var factory = FactoryForRequest(requestContext); - if (factory != null) - { - factory.ReleaseController(controller); - released = true; - } - } - - if (released == false) - base.ReleaseController(icontroller); - } - } -} diff --git a/src/Umbraco.Web/Mvc/ModelBindingException.cs b/src/Umbraco.Web/Mvc/ModelBindingException.cs deleted file mode 100644 index 548b548d4e..0000000000 --- a/src/Umbraco.Web/Mvc/ModelBindingException.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace Umbraco.Web.Mvc -{ - /// - /// The exception that is thrown when an error occurs while binding a source to a model. - /// - /// - [Serializable] - public class ModelBindingException : Exception - { - /// - /// Initializes a new instance of the class. - /// - public ModelBindingException() - { } - - /// - /// Initializes a new instance of the class. - /// - /// The message that describes the error. - public ModelBindingException(string message) - : base(message) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference ( in Visual Basic) if no inner exception is specified. - public ModelBindingException(string message, Exception innerException) - : base(message, innerException) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - protected ModelBindingException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} diff --git a/src/Umbraco.Web/Mvc/ModelBindingExceptionFilter.cs b/src/Umbraco.Web/Mvc/ModelBindingExceptionFilter.cs deleted file mode 100644 index b189867a89..0000000000 --- a/src/Umbraco.Web/Mvc/ModelBindingExceptionFilter.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Configuration; -using System.Net; -using System.Text.RegularExpressions; -using System.Web.Mvc; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration.Models; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - /// - /// An exception filter checking if we get a or with the same model. - /// In which case it returns a redirect to the same page after 1 sec if not in debug mode. - /// - /// - /// This is only enabled when running PureLive - /// - /// Migrated to .NET Core - internal class ModelBindingExceptionFilter : FilterAttribute, IExceptionFilter - { - private static readonly Regex GetPublishedModelsTypesRegex = new Regex("Umbraco.Web.PublishedModels.(\\w+)", RegexOptions.Compiled); - - public void OnException(ExceptionContext filterContext) - { - var settings = Current.Factory.GetInstance>().Value; - var disabled = settings?.Disabled ?? false; - if (Current.PublishedModelFactory.IsLiveFactory() - && !disabled - && !filterContext.ExceptionHandled - && ((filterContext.Exception is ModelBindingException || filterContext.Exception is InvalidCastException) - && IsMessageAboutTheSameModelType(filterContext.Exception.Message))) - { - filterContext.HttpContext.Response.Headers.Add(HttpResponseHeader.RetryAfter.ToString(), "1"); - filterContext.Result = new RedirectResult(filterContext.HttpContext.Request.RawUrl, false); - - filterContext.ExceptionHandled = true; - } - } - - /// - /// Returns true if the message is about two models with the same name. - /// - /// - /// Message could be something like: - /// - /// InvalidCastException: - /// [A]Umbraco.Web.PublishedModels.Home cannot be cast to [B]Umbraco.Web.PublishedModels.Home. Type A originates from 'App_Web_all.generated.cs.8f9494c4.rtdigm_z, Version=0.0.0.3, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\User\AppData\Local\Temp\Temporary ASP.NET Files\root\c5c63f4d\c168d9d4\App_Web_all.generated.cs.8f9494c4.rtdigm_z.dll'. Type B originates from 'App_Web_all.generated.cs.8f9494c4.rbyqlplu, Version=0.0.0.5, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\User\AppData\Local\Temp\Temporary ASP.NET Files\root\c5c63f4d\c168d9d4\App_Web_all.generated.cs.8f9494c4.rbyqlplu.dll'. - /// - /// - /// ModelBindingException: - /// Cannot bind source content type Umbraco.Web.PublishedModels.Home to model type Umbraco.Web.PublishedModels.Home. Both view and content models are PureLive, with different versions. The application is in an unstable state and is going to be restarted. The application is restarting now. - /// - /// - private bool IsMessageAboutTheSameModelType(string exceptionMessage) - { - var matches = GetPublishedModelsTypesRegex.Matches(exceptionMessage); - - if (matches.Count >= 2) - { - return string.Equals(matches[0].Value, matches[1].Value, StringComparison.InvariantCulture); - } - - return false; - } - } -} diff --git a/src/Umbraco.Web/Mvc/PreRenderViewActionFilterAttribute.cs b/src/Umbraco.Web/Mvc/PreRenderViewActionFilterAttribute.cs deleted file mode 100644 index 2e659eccf6..0000000000 --- a/src/Umbraco.Web/Mvc/PreRenderViewActionFilterAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace Umbraco.Web.Mvc -{ - /// Migrated already to .Net Core - public class PreRenderViewActionFilterAttribute : ActionFilterAttribute - { - public override void OnActionExecuted(ActionExecutedContext filterContext) - { - var umbController = filterContext.Controller as Controller; - if (umbController == null) - { - return; - } - - var result = filterContext.Result as ViewResultBase; - if (result == null) - { - return; - } - - var model = result.Model; - if (model == null) - { - return; - } - - var args = new ActionExecutedEventArgs(umbController, model); - OnActionExecuted(args); - - if (args.Model != model) - { - result.ViewData.Model = args.Model; - } - - base.OnActionExecuted(filterContext); - } - - - public static event EventHandler ActionExecuted; - - private static void OnActionExecuted(ActionExecutedEventArgs e) - { - EventHandler handler = ActionExecuted; - if (handler != null) handler(null, e); - } - } -} diff --git a/src/Umbraco.Web/Mvc/RenderControllerFactory.cs b/src/Umbraco.Web/Mvc/RenderControllerFactory.cs index c9734e24b0..091ace4d98 100644 --- a/src/Umbraco.Web/Mvc/RenderControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/RenderControllerFactory.cs @@ -1,45 +1,45 @@ -using System.Web.Mvc; -using System.Web.Routing; - -namespace Umbraco.Web.Mvc -{ - /// - /// A controller factory for the render pipeline of Umbraco. This controller factory tries to create a controller with the supplied - /// name, and falls back to UmbracoController if none was found. - /// - /// - public class RenderControllerFactory : UmbracoControllerFactory - { - /// - /// Determines whether this instance can handle the specified request. - /// - /// The request. - /// true if this instance can handle the specified request; otherwise, false. - /// - public override bool CanHandle(RequestContext request) - { - var dataToken = request.RouteData.DataTokens["area"]; - return dataToken == null || string.IsNullOrWhiteSpace(dataToken.ToString()); - } - - /// - /// Creates the controller - /// - /// - /// - /// - /// - /// We always set the correct ActionInvoker on our custom created controller, this is very important for route hijacking! - /// - public override IController CreateController(RequestContext requestContext, string controllerName) - { - var instance = base.CreateController(requestContext, controllerName); - if (instance is Controller controllerInstance) - { - //set the action invoker! - controllerInstance.ActionInvoker = new RenderActionInvoker(); - } - return instance; - } - } -} +// using System.Web.Mvc; +// using System.Web.Routing; +// +// namespace Umbraco.Web.Mvc +// { +// /// +// /// A controller factory for the render pipeline of Umbraco. This controller factory tries to create a controller with the supplied +// /// name, and falls back to UmbracoController if none was found. +// /// +// /// +// public class RenderControllerFactory : UmbracoControllerFactory +// { +// /// +// /// Determines whether this instance can handle the specified request. +// /// +// /// The request. +// /// true if this instance can handle the specified request; otherwise, false. +// /// +// public override bool CanHandle(RequestContext request) +// { +// var dataToken = request.RouteData.DataTokens["area"]; +// return dataToken == null || string.IsNullOrWhiteSpace(dataToken.ToString()); +// } +// +// /// +// /// Creates the controller +// /// +// /// +// /// +// /// +// /// +// /// We always set the correct ActionInvoker on our custom created controller, this is very important for route hijacking! +// /// +// public override IController CreateController(RequestContext requestContext, string controllerName) +// { +// var instance = base.CreateController(requestContext, controllerName); +// if (instance is Controller controllerInstance) +// { +// //set the action invoker! +// controllerInstance.ActionInvoker = new RenderActionInvoker(); +// } +// return instance; +// } +// } +// } diff --git a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs index 325f18d957..b4dde6c540 100644 --- a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs @@ -1,88 +1,88 @@ -using System; -using System.Web.Mvc; -using System.Web.Routing; -using System.Web.SessionState; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - /// - /// Abstract filtered controller factory used for all Umbraco controller factory implementations - /// - public abstract class UmbracoControllerFactory : IFilteredControllerFactory - { - private readonly OverridenDefaultControllerFactory _innerFactory = new OverridenDefaultControllerFactory(); - - public abstract bool CanHandle(RequestContext request); - - public virtual Type GetControllerType(RequestContext requestContext, string controllerName) - { - return _innerFactory.GetControllerType(requestContext, controllerName); - } - - /// - /// Creates the specified controller by using the specified request context. - /// - /// - /// The controller. - /// - /// The request context.The name of the controller. - public virtual IController CreateController(RequestContext requestContext, string controllerName) - { - var controllerType = GetControllerType(requestContext, controllerName) ?? - _innerFactory.GetControllerType( - requestContext, - ControllerExtensions.GetControllerName(Current.DefaultRenderMvcControllerType)); - - return _innerFactory.GetControllerInstance(requestContext, controllerType); - } - - /// - /// Gets the controller's session behavior. - /// - /// - /// The controller's session behavior. - /// - /// The request context.The name of the controller whose session behavior you want to get. - public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) - { - return ((IControllerFactory)_innerFactory).GetControllerSessionBehavior(requestContext, controllerName); - } - - /// - /// Releases the specified controller. - /// - /// The controller. - public virtual void ReleaseController(IController controller) - { - _innerFactory.ReleaseController(controller); - } - - /// - /// By default, only exposes which throws an exception - /// if the controller is not found. Since we want to try creating a controller, and then fall back to if one isn't found, - /// this nested class changes the visibility of 's internal methods in order to not have to rely on a try-catch. - /// - /// - internal class OverridenDefaultControllerFactory : ContainerControllerFactory - { - public OverridenDefaultControllerFactory() - : base(new Lazy(() => Current.Factory)) - { } - - public new IController GetControllerInstance(RequestContext requestContext, Type controllerType) - { - return base.GetControllerInstance(requestContext, controllerType); - } - - public new Type GetControllerType(RequestContext requestContext, string controllerName) - { - return controllerName.IsNullOrWhiteSpace() - ? null - : base.GetControllerType(requestContext, controllerName); - } - } - } -} +// using System; +// using System.Web.Mvc; +// using System.Web.Routing; +// using System.Web.SessionState; +// using Umbraco.Core; +// using Umbraco.Core.Composing; +// using Umbraco.Web.Composing; +// +// namespace Umbraco.Web.Mvc +// { +// /// +// /// Abstract filtered controller factory used for all Umbraco controller factory implementations +// /// +// public abstract class UmbracoControllerFactory : IFilteredControllerFactory +// { +// private readonly OverridenDefaultControllerFactory _innerFactory = new OverridenDefaultControllerFactory(); +// +// public abstract bool CanHandle(RequestContext request); +// +// public virtual Type GetControllerType(RequestContext requestContext, string controllerName) +// { +// return _innerFactory.GetControllerType(requestContext, controllerName); +// } +// +// /// +// /// Creates the specified controller by using the specified request context. +// /// +// /// +// /// The controller. +// /// +// /// The request context.The name of the controller. +// public virtual IController CreateController(RequestContext requestContext, string controllerName) +// { +// var controllerType = GetControllerType(requestContext, controllerName) ?? +// _innerFactory.GetControllerType( +// requestContext, +// ControllerExtensions.GetControllerName(Current.DefaultRenderMvcControllerType)); +// +// return _innerFactory.GetControllerInstance(requestContext, controllerType); +// } +// +// /// +// /// Gets the controller's session behavior. +// /// +// /// +// /// The controller's session behavior. +// /// +// /// The request context.The name of the controller whose session behavior you want to get. +// public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) +// { +// return ((IControllerFactory)_innerFactory).GetControllerSessionBehavior(requestContext, controllerName); +// } +// +// /// +// /// Releases the specified controller. +// /// +// /// The controller. +// public virtual void ReleaseController(IController controller) +// { +// _innerFactory.ReleaseController(controller); +// } +// +// /// +// /// By default, only exposes which throws an exception +// /// if the controller is not found. Since we want to try creating a controller, and then fall back to if one isn't found, +// /// this nested class changes the visibility of 's internal methods in order to not have to rely on a try-catch. +// /// +// /// +// internal class OverridenDefaultControllerFactory : ContainerControllerFactory +// { +// public OverridenDefaultControllerFactory() +// : base(new Lazy(() => Current.Factory)) +// { } +// +// public new IController GetControllerInstance(RequestContext requestContext, Type controllerType) +// { +// return base.GetControllerInstance(requestContext, controllerType); +// } +// +// public new Type GetControllerType(RequestContext requestContext, string controllerName) +// { +// return controllerName.IsNullOrWhiteSpace() +// ? null +// : base.GetControllerType(requestContext, controllerName); +// } +// } +// } +// } diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index f461fb9a22..7eff581bab 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -143,59 +143,7 @@ namespace Umbraco.Web.Mvc if (ViewContext.RouteData.DataTokens.ContainsKey(Constants.DataTokenCurrentViewContext) == false) ViewContext.RouteData.DataTokens.Add(Constants.DataTokenCurrentViewContext, ViewContext); } - - // maps model - protected override void SetViewData(ViewDataDictionary viewData) - { - // capture the model before we tinker with the viewData - var viewDataModel = viewData.Model; - - // map the view data (may change its type, may set model to null) - viewData = MapViewDataDictionary(viewData, typeof (TModel)); - - // bind the model - viewData.Model = ContentModelBinder.BindModel(viewDataModel, typeof (TModel)); - - // set the view data - base.SetViewData(viewData); - } - - // viewData is the ViewDataDictionary (maybe ) that we have - // modelType is the type of the model that we need to bind to - // - // figure out whether viewData can accept modelType else replace it - // - private static ViewDataDictionary MapViewDataDictionary(ViewDataDictionary viewData, Type modelType) - { - var viewDataType = viewData.GetType(); - - // if viewData is not generic then it is a simple ViewDataDictionary instance and its - // Model property is of type 'object' and will accept anything, so it is safe to use - // viewData - if (viewDataType.IsGenericType == false) - return viewData; - - // ensure it is the proper generic type - var def = viewDataType.GetGenericTypeDefinition(); - if (def != typeof(ViewDataDictionary<>)) - throw new Exception("Could not map viewData of type \"" + viewDataType.FullName + "\"."); - - // get the viewData model type and compare with the actual view model type: - // viewData is ViewDataDictionary and we will want to assign an - // object of type modelType to the Model property of type viewDataModelType, we - // need to check whether that is possible - var viewDataModelType = viewDataType.GenericTypeArguments[0]; - - if (viewDataModelType.IsAssignableFrom(modelType)) - return viewData; - - // if not possible then we need to create a new ViewDataDictionary - var nViewDataType = typeof(ViewDataDictionary<>).MakeGenericType(modelType); - var tViewData = new ViewDataDictionary(viewData) { Model = null }; // temp view data to copy values - var nViewData = (ViewDataDictionary)Activator.CreateInstance(nViewDataType, tViewData); - return nViewData; - } - + /// /// This will detect the end /body tag and insert the preview badge if in preview mode /// diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index a5c7db12c9..d02ccdd01e 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -89,16 +89,13 @@ namespace Umbraco.Web.Runtime MvcHandler.DisableMvcResponseHeader = true; // set master controller factory - var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories); - ControllerBuilder.Current.SetControllerFactory(controllerFactory); + // var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories); + // ControllerBuilder.Current.SetControllerFactory(controllerFactory); // set the render & plugin view engines ViewEngines.Engines.Add(new RenderViewEngine(_hostingEnvironment)); ViewEngines.Engines.Add(new PluginViewEngine()); - - //set model binder - ModelBinderProviders.BinderProviders.Add(ContentModelBinder.Instance); // is a provider - + ////add the profiling action filter //GlobalFilters.Filters.Add(new ProfilingActionFilter()); diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 591a3698e7..cfe9dcdad2 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -58,17 +58,13 @@ namespace Umbraco.Web.Runtime composition // TODO: This will depend on if we use ServiceBasedControllerActivator - see notes in Startup.cs - .ComposeUmbracoControllers(GetType().Assembly) + //.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()); - // 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.FilteredControllerFactory() - .Append(); // auto-register views composition.RegisterAuto(typeof(UmbracoViewPage<>)); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index d7bd025e2a..a2a15ada05 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -144,16 +144,11 @@ - - - - - @@ -168,13 +163,8 @@ - - - - - @@ -209,7 +199,6 @@ - @@ -220,10 +209,7 @@ - - - @@ -237,7 +223,6 @@ - @@ -261,7 +246,6 @@ - @@ -336,11 +320,8 @@ - - - diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 0be333d28c..baeab5634c 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -80,10 +80,7 @@ namespace Umbraco.Web return new VoidProfiler(); } - var webProfiler = new WebProfiler(); - webProfiler.Start(); - - return webProfiler; + return new VoidProfiler(); } protected UmbracoApplicationBase(ILogger logger, ILoggerFactory loggerFactory, SecuritySettings securitySettings, GlobalSettings globalSettings, ConnectionStrings connectionStrings, IIOHelper ioHelper, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo)