diff --git a/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs b/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
index 422673a823..e78a6e4608 100644
--- a/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
+++ b/src/Umbraco.Core/Events/UmbracoApplicationStarting.cs
@@ -1,5 +1,9 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
namespace Umbraco.Core.Events
{
+
public class UmbracoApplicationStarting : INotification
{
///
diff --git a/src/Umbraco.Core/Events/UmbracoRequestBegin.cs b/src/Umbraco.Core/Events/UmbracoRequestBegin.cs
new file mode 100644
index 0000000000..c72ddc904d
--- /dev/null
+++ b/src/Umbraco.Core/Events/UmbracoRequestBegin.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using Umbraco.Web;
+
+namespace Umbraco.Core.Events
+{
+ ///
+ /// Notification raised on each request begin.
+ ///
+ public class UmbracoRequestBegin : INotification
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public UmbracoRequestBegin(IUmbracoContext umbracoContext) => UmbracoContext = umbracoContext;
+
+ ///
+ /// Gets the
+ ///
+ public IUmbracoContext UmbracoContext { get; }
+ }
+}
diff --git a/src/Umbraco.Web.Common/Events/UmbracoRequestEnd.cs b/src/Umbraco.Core/Events/UmbracoRequestEnd.cs
similarity index 60%
rename from src/Umbraco.Web.Common/Events/UmbracoRequestEnd.cs
rename to src/Umbraco.Core/Events/UmbracoRequestEnd.cs
index 459eca2bba..1988a2dd50 100644
--- a/src/Umbraco.Web.Common/Events/UmbracoRequestEnd.cs
+++ b/src/Umbraco.Core/Events/UmbracoRequestEnd.cs
@@ -1,7 +1,7 @@
-// Copyright (c) Umbraco.
+// Copyright (c) Umbraco.
// See LICENSE for more details.
-using Microsoft.AspNetCore.Http;
+using Umbraco.Web;
namespace Umbraco.Core.Events
{
@@ -13,11 +13,11 @@ namespace Umbraco.Core.Events
///
/// Initializes a new instance of the class.
///
- public UmbracoRequestEnd(HttpContext httpContext) => HttpContext = httpContext;
+ public UmbracoRequestEnd(IUmbracoContext umbracoContext) => UmbracoContext = umbracoContext;
///
- /// Gets the
+ /// Gets the
///
- public HttpContext HttpContext { get; }
+ public IUmbracoContext UmbracoContext { get; }
}
}
diff --git a/src/Umbraco.Core/Routing/EnsureRoutableOutcome.cs b/src/Umbraco.Core/Routing/EnsureRoutableOutcome.cs
deleted file mode 100644
index 0c6ac7c564..0000000000
--- a/src/Umbraco.Core/Routing/EnsureRoutableOutcome.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-namespace Umbraco.Web.Routing
-{
- ///
- /// Represents the outcome of trying to route an incoming request.
- ///
- public enum EnsureRoutableOutcome
- {
- ///
- /// Request routes to a document.
- ///
- ///
- /// Umbraco was ready and configured, and has content.
- /// The request looks like it can be a route to a document. This does not
- /// mean that there *is* a matching document, ie the request might end up returning
- /// 404.
- ///
- IsRoutable = 0,
-
- ///
- /// Request does not route to a document.
- ///
- ///
- /// Umbraco was ready and configured, and has content.
- /// The request does not look like it can be a route to a document. Can be
- /// anything else eg back-office, surface controller...
- ///
- NotDocumentRequest = 10,
-
- ///
- /// Umbraco was not ready.
- ///
- NotReady = 11,
-
- ///
- /// There was no content at all.
- ///
- NoContent = 12
- }
-}
diff --git a/src/Umbraco.Core/Routing/RoutableAttemptEventArgs.cs b/src/Umbraco.Core/Routing/RoutableAttemptEventArgs.cs
deleted file mode 100644
index 9f80d8ed3f..0000000000
--- a/src/Umbraco.Core/Routing/RoutableAttemptEventArgs.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Umbraco.Web.Routing
-{
- ///
- /// Event args containing information about why the request was not routable, or if it is routable
- ///
- public class RoutableAttemptEventArgs : UmbracoRequestEventArgs
- {
- public EnsureRoutableOutcome Outcome { get; private set; }
-
- public RoutableAttemptEventArgs(EnsureRoutableOutcome reason, IUmbracoContext umbracoContext)
- : base(umbracoContext)
- {
- Outcome = reason;
- }
- }
-}
diff --git a/src/Umbraco.Core/Routing/UmbracoRequestEventArgs.cs b/src/Umbraco.Core/Routing/UmbracoRequestEventArgs.cs
deleted file mode 100644
index d93a27ddf4..0000000000
--- a/src/Umbraco.Core/Routing/UmbracoRequestEventArgs.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-
-namespace Umbraco.Web.Routing
-{
- ///
- /// Event args used for event launched during a request (like in the UmbracoModule)
- ///
- public class UmbracoRequestEventArgs : EventArgs
- {
- public IUmbracoContext UmbracoContext { get; private set; }
-
- public UmbracoRequestEventArgs(IUmbracoContext umbracoContext)
- {
- UmbracoContext = umbracoContext;
- }
- }
-}
diff --git a/src/Umbraco.Core/Web/IRequestAccessor.cs b/src/Umbraco.Core/Web/IRequestAccessor.cs
index 85ab5cff97..275c96bf23 100644
--- a/src/Umbraco.Core/Web/IRequestAccessor.cs
+++ b/src/Umbraco.Core/Web/IRequestAccessor.cs
@@ -5,13 +5,22 @@ namespace Umbraco.Web
{
public interface IRequestAccessor
{
+ ///
+ /// Returns the request/form/querystring value for the given name
+ ///
string GetRequestValue(string name);
+
+ ///
+ /// Returns the query string value for the given name
+ ///
string GetQueryStringValue(string name);
- event EventHandler EndRequest;
- event EventHandler RouteAttempt;
+
+ ///
+ /// Returns the current request uri
+ ///
Uri GetRequestUrl();
- // TODO: Not sure this belongs here but we can leave it for now
+ // TODO: This doesn't belongs here
Uri GetApplicationUrl();
}
}
diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
index 1ad2b44740..fc3f66c28f 100644
--- a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
+++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
@@ -11,10 +11,9 @@ namespace Umbraco.Infrastructure.Cache
///
/// Ensures that distributed cache events are setup and the is initialized
///
- public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler
+ public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler, INotificationHandler
{
private readonly IServerMessenger _messenger;
- private readonly IRequestAccessor _requestAccessor;
private readonly IUmbracoDatabaseFactory _databaseFactory;
private readonly IDistributedCacheBinder _distributedCacheBinder;
private readonly ILogger _logger;
@@ -24,12 +23,10 @@ namespace Umbraco.Infrastructure.Cache
///
public DatabaseServerMessengerNotificationHandler(
IServerMessenger serverMessenger,
- IRequestAccessor requestAccessor,
IUmbracoDatabaseFactory databaseFactory,
IDistributedCacheBinder distributedCacheBinder,
ILogger logger)
{
- _requestAccessor = requestAccessor;
_databaseFactory = databaseFactory;
_distributedCacheBinder = distributedCacheBinder;
_logger = logger;
@@ -38,19 +35,6 @@ namespace Umbraco.Infrastructure.Cache
///
public void Handle(UmbracoApplicationStarting notification)
- {
- // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services.
- // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL
- // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured).
- // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available
- // for the hosted services to use when the HTTP request is not available.
- _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce;
- _requestAccessor.EndRequest += EndRequest;
-
- Startup();
- }
-
- private void Startup()
{
if (_databaseFactory.CanConnect == false)
{
@@ -65,28 +49,9 @@ namespace Umbraco.Infrastructure.Cache
}
}
- // TODO: I don't really know or think that the Application Url plays a role anymore with the DB dist cache,
- // this might be really old stuff. I 'think' all this is doing is ensuring that the IRequestAccessor.GetApplicationUrl
- // is definitely called during the first request. If that is still required, that logic doesn't belong here. That logic
- // should be part of it's own service/middleware. There's also TODO notes within IRequestAccessor.GetApplicationUrl directly
- // mentioning that the property doesn't belong on that service either. This should be investigated and resolved in a separate task.
- private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e)
- {
- if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
- {
- _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce;
- EnsureApplicationUrl();
- }
- }
-
- // By retrieving the application URL within the context of a request (as we are here in responding
- // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for
- // future requests that may not be within an HTTP request (e.g. from hosted services).
- private void EnsureApplicationUrl() => _requestAccessor.GetApplicationUrl();
-
///
/// Clear the batch on end request
///
- private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.SendMessages();
+ public void Handle(UmbracoRequestEnd notification) => _messenger?.SendMessages();
}
}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs
index b88c2346a7..e816972989 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.DistributedCache.cs
@@ -38,6 +38,7 @@ namespace Umbraco.Infrastructure.DependencyInjection
builder.SetDatabaseServerMessengerCallbacks(GetCallbacks);
builder.SetServerMessenger();
builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
return builder;
}
diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
index cf5235387d..eafc006c26 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
@@ -117,7 +117,7 @@ namespace Umbraco.ModelsBuilder.Embedded
public void Handle(UmbracoRequestEnd notification)
{
- if (IsEnabled && _mainDom.IsMainDom && !notification.HttpContext.Request.IsClientSideRequest())
+ if (IsEnabled && _mainDom.IsMainDom)
{
GenerateModelsIfRequested();
}
diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
deleted file mode 100644
index 2ec0113c2f..0000000000
--- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using System;
-using System.Threading;
-using Microsoft.Extensions.Logging;
-using Moq;
-using NUnit.Framework;
-using Umbraco.Core;
-using Umbraco.Core.Configuration.Models;
-using Umbraco.Tests.Common.Builders;
-using Umbraco.Tests.TestHelpers;
-using Umbraco.Web;
-
-namespace Umbraco.Tests.Routing
-{
- [TestFixture]
- [Apartment(ApartmentState.STA)]
- public class UmbracoModuleTests : BaseWebTest
- {
- private UmbracoInjectedModule _module;
-
- public override void SetUp()
- {
- base.SetUp();
-
- // FIXME: be able to get the UmbracoModule from the container. any reason settings were from testobjects?
- //create the module
- var logger = Mock.Of();
-
- var globalSettings = new GlobalSettings { ReservedPaths = GlobalSettings.StaticReservedPaths + "~/umbraco" };
- var runtime = Umbraco.Core.RuntimeState.Booting();
-
- _module = new UmbracoInjectedModule
- (
- runtime,
- logger,
- Mock.Of(),
- globalSettings,
- HostingEnvironment
- );
-
- runtime.Level = RuntimeLevel.Run;
-
-
- //SettingsForTests.ReservedPaths = "~/umbraco,~/install/";
- //SettingsForTests.ReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd";
-
- }
-
- public override void TearDown()
- {
- base.TearDown();
-
- _module.DisposeIfDisposable();
- }
-
- // do not test for /base here as it's handled before EnsureUmbracoRoutablePage is called
- [TestCase("/umbraco_client/Tree/treeIcons.css", false)]
- [TestCase("/umbraco_client/Tree/Themes/umbraco/style.css?cdv=37", false)]
- [TestCase("/umbraco/editContent.aspx", false)]
- [TestCase("/install/default.aspx", false)]
- [TestCase("/install/?installStep=license", false)]
- [TestCase("/install?installStep=license", false)]
- [TestCase("/install/test.aspx", false)]
- [TestCase("/config/splashes/noNodes.aspx", false)]
- [TestCase("/", true)]
- [TestCase("/home.aspx", true)]
- [TestCase("/umbraco-test", true)]
- [TestCase("/install-test", true)]
- public void Ensure_Request_Routable(string url, bool assert)
- {
- var httpContextFactory = new FakeHttpContextFactory(url);
- var httpContext = httpContextFactory.HttpContext;
- var umbracoContext = GetUmbracoContext(url);
-
- var result = _module.EnsureUmbracoRoutablePage(umbracoContext, httpContext);
-
- Assert.AreEqual(assert, result.Success);
- }
-
- //NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
- // we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
- // to ensure that each one is individually tested.
-
- //[TestCase("/", 1046)]
- //[TestCase("/home.aspx", 1046)]
- //[TestCase("/home/sub1.aspx", 1173)]
- //[TestCase("/home.aspx?altTemplate=blah", 1046)]
- //public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
- //{
- // var httpContextFactory = new FakeHttpContextFactory(url);
- // var httpContext = httpContextFactory.HttpContext;
- // var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
- // var contentStore = new ContentStore(umbracoContext);
- // var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
- // umbracoContext.RoutingContext = new RoutingContext(
- // new IPublishedContentLookup[] {new LookupByNiceUrl()},
- // new DefaultLastChanceLookup(),
- // contentStore,
- // niceUrls);
-
- // StateHelper.HttpContext = httpContext;
-
- // //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
- // //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
- // Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
-
- // //need to create a template with id 1045
- // var template = Template.MakeNew("test", new User(0));
-
- // SetupUmbracoContextForTest(umbracoContext, template);
-
- // _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
-
- // Assert.IsNotNull(umbracoContext.PublishedContentRequest);
- // Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
- // Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
- // Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
- // Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
- // Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
- // Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
-
- //}
-
- }
-}
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index 78f9fc3013..c306451f66 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -226,7 +226,6 @@ namespace Umbraco.Tests.Testing
services.AddUnique(ipResolver);
services.AddUnique();
services.AddUnique(TestHelper.ShortStringHelper);
- services.AddUnique();
services.AddUnique();
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index b09787dd2c..f614ac6130 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -243,7 +243,6 @@
-
diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs
index c88612c2c7..7e1dbb3c9c 100644
--- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs
+++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Options;
@@ -10,42 +11,45 @@ using Umbraco.Web.Routing;
namespace Umbraco.Web.Common.AspNetCore
{
- public class AspNetCoreRequestAccessor : IRequestAccessor, INotificationHandler, INotificationHandler
+ public class AspNetCoreRequestAccessor : IRequestAccessor, INotificationHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly WebRoutingSettings _webRoutingSettings;
private readonly ISet _applicationUrls = new HashSet();
private Uri _currentApplicationUrl;
+ private object _initLocker = new object();
+ private bool _hasAppUrl = false;
+ private bool _isInit = false;
- public AspNetCoreRequestAccessor(IHttpContextAccessor httpContextAccessor,
- IUmbracoContextAccessor umbracoContextAccessor,
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AspNetCoreRequestAccessor(
+ IHttpContextAccessor httpContextAccessor,
IOptions webRoutingSettings)
{
_httpContextAccessor = httpContextAccessor;
- _umbracoContextAccessor = umbracoContextAccessor;
_webRoutingSettings = webRoutingSettings.Value;
}
-
+ ///
public string GetRequestValue(string name) => GetFormValue(name) ?? GetQueryStringValue(name);
- public string GetFormValue(string name)
+ private string GetFormValue(string name)
{
var request = _httpContextAccessor.GetRequiredHttpContext().Request;
if (!request.HasFormContentType) return null;
return request.Form[name];
}
+ ///
public string GetQueryStringValue(string name) => _httpContextAccessor.GetRequiredHttpContext().Request.Query[name];
- public event EventHandler EndRequest;
-
- public event EventHandler RouteAttempt;
-
+ ///
public Uri GetRequestUrl() => _httpContextAccessor.HttpContext != null ? new Uri(_httpContextAccessor.HttpContext.Request.GetEncodedUrl()) : null;
+ ///
public Uri GetApplicationUrl()
{
// Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
@@ -80,17 +84,16 @@ namespace Umbraco.Web.Common.AspNetCore
return _currentApplicationUrl;
}
+ ///
+ /// This just initializes the application URL on first request attempt
+ /// TODO: This doesn't belong here, the GetApplicationUrl doesn't belong to IRequestAccessor
+ /// this should be part of middleware not a lazy init based on an INotification
+ ///
public void Handle(UmbracoRequestBegin notification)
- {
- var reason = EnsureRoutableOutcome.IsRoutable; //TODO get the correct value here like in UmbracoInjectedModule
- RouteAttempt?.Invoke(this, new RoutableAttemptEventArgs(reason, _umbracoContextAccessor.UmbracoContext));
- }
-
- public void Handle(UmbracoRequestEnd notification)
- {
- EndRequest?.Invoke(this, new UmbracoRequestEventArgs(_umbracoContextAccessor.UmbracoContext));
- }
-
-
+ => LazyInitializer.EnsureInitialized(ref _hasAppUrl, ref _isInit, ref _initLocker, () =>
+ {
+ GetApplicationUrl();
+ return true;
+ });
}
}
diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
index 4b9953edf7..2dfb98d6e2 100644
--- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -233,7 +233,6 @@ namespace Umbraco.Web.Common.DependencyInjection
builder.Services.AddUnique();
builder.Services.AddUnique();
builder.AddNotificationHandler();
- builder.AddNotificationHandler();
// Password hasher
builder.Services.AddUnique();
diff --git a/src/Umbraco.Web.Common/Events/UmbracoRequestBegin.cs b/src/Umbraco.Web.Common/Events/UmbracoRequestBegin.cs
deleted file mode 100644
index 82d9edacbc..0000000000
--- a/src/Umbraco.Web.Common/Events/UmbracoRequestBegin.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Umbraco.
-// See LICENSE for more details.
-
-using Microsoft.AspNetCore.Http;
-
-namespace Umbraco.Core.Events
-{
- ///
- /// Notification raised on each request begin.
- ///
- public class UmbracoRequestBegin : INotification
- {
- public UmbracoRequestBegin(HttpContext httpContext)
- {
- HttpContext = httpContext;
- }
-
- public HttpContext HttpContext { get; }
- };
-}
diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs
index 069c38d3c5..cee2d0e6e7 100644
--- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs
+++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs
@@ -95,7 +95,7 @@ namespace Umbraco.Web.Common.Middleware
try
{
- await _eventAggregator.PublishAsync(new UmbracoRequestBegin(context));
+ await _eventAggregator.PublishAsync(new UmbracoRequestBegin(umbracoContextReference.UmbracoContext));
}
catch (Exception ex)
{
@@ -111,7 +111,7 @@ namespace Umbraco.Web.Common.Middleware
}
finally
{
- await _eventAggregator.PublishAsync(new UmbracoRequestEnd(context));
+ await _eventAggregator.PublishAsync(new UmbracoRequestEnd(umbracoContextReference.UmbracoContext));
}
}
}
@@ -119,7 +119,7 @@ namespace Umbraco.Web.Common.Middleware
{
if (isFrontEndRequest)
{
- LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
+ LogHttpRequest.TryGetCurrentHttpRequestId(out Guid httpRequestId, _requestCache);
_logger.LogTrace("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, pathAndQuery, DateTime.Now.Subtract(umbracoContextReference.UmbracoContext.ObjectCreated).TotalMilliseconds);
}
diff --git a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs b/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs
deleted file mode 100644
index ae38dc2c05..0000000000
--- a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.Options;
-using Umbraco.Core.Configuration.Models;
-using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Web.Routing;
-
-namespace Umbraco.Web.AspNet
-{
- public class AspNetRequestAccessor : IRequestAccessor
- {
- private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly WebRoutingSettings _webRoutingSettings;
- private readonly ISet _applicationUrls = new HashSet();
- private Uri _currentApplicationUrl;
- public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor, IOptions webRoutingSettings)
- {
- _httpContextAccessor = httpContextAccessor;
- _webRoutingSettings = webRoutingSettings.Value;
-
- UmbracoModule.EndRequest += OnEndRequest;
- UmbracoModule.RouteAttempt += OnRouteAttempt;
- }
-
-
-
- public string GetRequestValue(string name)
- {
- return _httpContextAccessor.GetRequiredHttpContext().Request[name];
- }
-
- public string GetQueryStringValue(string name)
- {
- return _httpContextAccessor.GetRequiredHttpContext().Request.QueryString[name];
- }
-
- private void OnEndRequest(object sender, UmbracoRequestEventArgs args)
- {
- EndRequest?.Invoke(sender, args);
- }
-
- private void OnRouteAttempt(object sender, RoutableAttemptEventArgs args)
- {
- RouteAttempt?.Invoke(sender, args);
- }
- public event EventHandler EndRequest;
- public event EventHandler RouteAttempt;
- public Uri GetRequestUrl() => _httpContextAccessor.HttpContext?.Request.Url;
- public Uri GetApplicationUrl()
- {
- //Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
- // it changes the URL to `localhost:80` which actually doesn't work for pinging itself, it only works internally in Azure. The ironic part
- // about this is that this is here specifically for the slot swap scenario https://issues.umbraco.org/issue/U4-10626
-
-
- // see U4-10626 - in some cases we want to reset the application url
- // (this is a simplified version of what was in 7.x)
- // note: should this be optional? is it expensive?
-
- if (!(_webRoutingSettings.UmbracoApplicationUrl is null))
- {
- return new Uri(_webRoutingSettings.UmbracoApplicationUrl);
- }
-
- var request = _httpContextAccessor.HttpContext?.Request;
-
- var url = request?.Url.GetLeftPart(UriPartial.Authority);
- var change = url != null && !_applicationUrls.Contains(url);
- if (change)
- {
- _applicationUrls.Add(url);
-
- _currentApplicationUrl ??= new Uri(url);
- }
-
- return _currentApplicationUrl;
- }
- }
-}
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index d4e989854f..3f166c5747 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -21,9 +21,6 @@ namespace Umbraco.Web.Runtime
{
base.Compose(builder);
- builder.Services.AddTransient();
-
-
// register membership stuff
builder.Services.AddTransient(factory => MembershipProviderExtensions.GetMembersMembershipProvider());
builder.Services.AddTransient(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetRequiredService()));
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index f5445a4bc9..2113175e51 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -131,7 +131,6 @@
-
@@ -177,7 +176,6 @@
-
@@ -245,7 +243,6 @@
Code
-
Component
diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs
deleted file mode 100644
index b50f4ce23e..0000000000
--- a/src/Umbraco.Web/UmbracoInjectedModule.cs
+++ /dev/null
@@ -1,243 +0,0 @@
-using System;
-using System.Web;
-using System.Web.Routing;
-using Microsoft.Extensions.Logging;
-using Umbraco.Core;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Configuration.Models;
-using Umbraco.Core.Exceptions;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.Security;
-using Umbraco.Web.Composing;
-using Umbraco.Web.Routing;
-
-namespace Umbraco.Web
-{
- // notes
- //
- // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?!
- //
- // context.RewritePath supports ~/ or else must begin with /vdir
- // Request.RawUrl is still there
- // response.Redirect does?! always remap to /vdir?!
-
- ///
- /// Represents the main Umbraco module.
- ///
- ///
- /// Is registered by the .
- /// Do *not* try to use that one as a module in web.config.
- ///
- public class UmbracoInjectedModule : IHttpModule
- {
- private readonly IRuntimeState _runtime;
- private readonly ILogger _logger;
- private readonly IUmbracoContextFactory _umbracoContextFactory;
- private readonly GlobalSettings _globalSettings;
- private readonly IHostingEnvironment _hostingEnvironment;
-
- public UmbracoInjectedModule(
- IRuntimeState runtime,
- ILogger logger,
- IUmbracoContextFactory umbracoContextFactory,
- GlobalSettings globalSettings,
- IHostingEnvironment hostingEnvironment)
- {
- _runtime = runtime;
- _logger = logger;
- _umbracoContextFactory = umbracoContextFactory;
- _globalSettings = globalSettings;
- _hostingEnvironment = hostingEnvironment;
- }
-
- ///
- /// Begins to process a request.
- ///
- private void BeginRequest(HttpContextBase httpContext)
- {
- // write the trace output for diagnostics at the end of the request
- httpContext.Trace.Write("UmbracoModule", "Umbraco request begins");
-
- // ok, process
-
- // TODO: should we move this to after we've ensured we are processing a routable page?
- // ensure there's an UmbracoContext registered for the current request
- // registers the context reference so its disposed at end of request
- var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();
- httpContext.DisposeOnPipelineCompleted(umbracoContextReference);
- }
-
- ///
- /// Processes the Umbraco Request
- ///
- ///
- /// This will check if we are trying to route to the default back office page (i.e. ~/Umbraco/ or ~/Umbraco or ~/Umbraco/Default )
- /// and ensure that the MVC handler executes for that. This is required because the route for /Umbraco will never execute because
- /// files/folders exist there and we cannot set the RouteCollection.RouteExistingFiles = true since that will muck a lot of other things up.
- /// So we handle it here and explicitly execute the MVC controller.
- ///
- void ProcessRequest(HttpContextBase httpContext)
- {
-
- var umbracoContext = Current.UmbracoContext;
-
- // do not process if this request is not a front-end routable page
- var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext);
-
- // raise event here
- UmbracoModule.OnRouteAttempt(this, new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext));
- if (isRoutableAttempt.Success == false) return;
- }
-
- ///
- /// Checks the current request and ensures that it is routable based on the structure of the request and URI
- ///
- internal Attempt EnsureUmbracoRoutablePage(IUmbracoContext context, HttpContextBase httpContext)
- {
- var uri = context.OriginalRequestUrl;
-
- var reason = EnsureRoutableOutcome.IsRoutable;
-
- //// ensure this is a document request
- //if (!_routableDocumentLookup.IsDocumentRequest(httpContext, context.OriginalRequestUrl))
- //{
- // reason = EnsureRoutableOutcome.NotDocumentRequest;
- //}
-
- // ensure the runtime is in the proper state
- // and deal with needed redirects, etc
- if (!EnsureRuntime(httpContext, uri))
- {
- reason = EnsureRoutableOutcome.NotReady;
- }
- // ensure Umbraco has documents to serve
- else if (!EnsureHasContent(context, httpContext))
- {
- reason = EnsureRoutableOutcome.NoContent;
- }
-
- return Attempt.If(reason == EnsureRoutableOutcome.IsRoutable, reason);
- }
-
- // TODO: Where should this execute in netcore? This will have to be a middleware
- // executing before UseRouting so that it is done before any endpoint routing takes place.
- private bool EnsureRuntime(HttpContextBase httpContext, Uri uri)
- {
- var level = _runtime.Level;
- switch (level)
- {
- // we should never handle Unknown nor Boot: the runtime boots in Application_Start
- // and as long as it has not booted, no request other than the initial request is
- // going to be served (see https://stackoverflow.com/a/21402100)
- // we should never handle BootFailed: if boot failed, the pipeline should not run
- // at all
- case RuntimeLevel.Unknown:
- case RuntimeLevel.Boot:
- case RuntimeLevel.BootFailed:
- throw new PanicException($"Unexpected runtime level: {level}.");
-
- case RuntimeLevel.Run:
- // ok
- return true;
-
- case RuntimeLevel.Install:
- case RuntimeLevel.Upgrade:
-
- // NOTE: We have moved the logic that was here to netcore already
-
- return false; // cannot serve content
-
- default:
- throw new NotSupportedException($"Unexpected runtime level: {level}.");
- }
- }
-
- // ensures Umbraco has at least one published node
- // if not, rewrites to splash and return false
- // if yes, return true
- private bool EnsureHasContent(IUmbracoContext context, HttpContextBase httpContext)
- {
- if (context.Content.HasContent())
- return true;
-
- _logger.LogWarning("Umbraco has no content");
-
- if (RouteTable.Routes[Constants.Web.NoContentRouteName] is Route route)
- {
- httpContext.RewritePath(route.Url);
- }
-
- return false;
- }
-
- ///
- /// Rewrites to the default back office page.
- ///
- ///
- private void RewriteToBackOfficeHandler(HttpContextBase context)
- {
- // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any)
- var rewritePath = _globalSettings.GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/Default";
- // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc)
- context.RewritePath(rewritePath, "", "", false);
-
- //if it is MVC we need to do something special, we are not using TransferRequest as this will
- //require us to rewrite the path with query strings and then re-parse the query strings, this would
- //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create
- //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does:
- // * Looks up the route based on the new rewritten URL
- // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route
- //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal
- //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink
- //a bunch of things!
- var urlRouting = new UrlRoutingModule();
- urlRouting.PostResolveRequestCache(context);
- }
-
-
-
- #region IHttpModule
-
- ///
- /// Initialize the module, this will trigger for each new application
- /// and there may be more than 1 application per application domain
- ///
- ///
- public void Init(HttpApplication app)
- {
- app.BeginRequest += (sender, e) =>
- {
- var httpContext = ((HttpApplication) sender).Context;
-
- BeginRequest(new HttpContextWrapper(httpContext));
- };
-
- app.PostAuthenticateRequest += (sender, e) =>
- {
- var httpContext = ((HttpApplication) sender).Context;
- //ensure the thread culture is set
- httpContext.User?.Identity?.EnsureCulture();
- };
-
- app.PostResolveRequestCache += (sender, e) =>
- {
- var httpContext = ((HttpApplication) sender).Context;
- ProcessRequest(new HttpContextWrapper(httpContext));
- };
-
- app.EndRequest += (sender, args) =>
- {
- var httpContext = ((HttpApplication) sender).Context;
-
- UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(Current.UmbracoContext));
- };
- }
-
- public void Dispose()
- { }
-
- #endregion
-
-
- }
-}
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
deleted file mode 100644
index 2f9c6d518a..0000000000
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Web;
-using Microsoft.Extensions.Logging;
-using Umbraco.Core;
-using Umbraco.Web.Composing;
-using Umbraco.Web.Routing;
-
-namespace Umbraco.Web
-{
- ///
- /// Represents the main Umbraco module.
- ///
- ///
- /// Register that one in web.config.
- /// It will inject which contains most of the actual code.
- ///
- public class UmbracoModule : ModuleInjector
- {
- ///
- /// Occurs when...
- ///
- internal static event EventHandler RouteAttempt;
-
- ///
- /// Occurs when...
- ///
- public static event EventHandler EndRequest;
-
- ///
- /// Triggers the RouteAttempt event.
- ///
- internal static void OnRouteAttempt(object sender, RoutableAttemptEventArgs args)
- {
- RouteAttempt?.Invoke(sender, args);
- }
-
- ///
- /// Triggers the EndRequest event.
- ///
- internal static void OnEndRequest(object sender, UmbracoRequestEventArgs args)
- {
- EndRequest?.Invoke(sender, args);
- }
- }
-}