public async Task Invoke(HttpContext httpContext) { // Ensure all ShellContext are loaded and available. _orchardHost.Initialize(); var shellSetting = _runningShellTable.Match(httpContext); // Register the shell settings as a custom feature. httpContext.Features.Set(shellSetting); // We only serve the next request if the tenant has been resolved. if (shellSetting != null) { var shellContext = _orchardHost.GetOrCreateShellContext(shellSetting); var existingRequestServices = httpContext.RequestServices; var scope = shellContext.CreateServiceScope(); try { httpContext.RequestServices = scope.ServiceProvider; if (!shellContext.IsActivated) { lock (shellContext) { // The tenant gets activated here if (!shellContext.IsActivated) { var tenantEvents = scope.ServiceProvider .GetServices <IModularTenantEvents>(); foreach (var tenantEvent in tenantEvents) { tenantEvent.ActivatingAsync().Wait(); } httpContext.Items["BuildPipeline"] = true; shellContext.IsActivated = true; foreach (var tenantEvent in tenantEvents) { tenantEvent.ActivatedAsync().Wait(); } } } } shellContext.RequestStarted(); await _next.Invoke(httpContext); } finally { // We dispose httpContext.RequestServices and not a local reference in case another middleware changed it (httpContext.RequestServices as IDisposable)?.Dispose(); shellContext.RequestEnded(); httpContext.RequestServices = existingRequestServices; } } }
public async Task Invoke(HttpContext httpContext) { // Ensure all ShellContext are loaded and available. _orchardHost.Initialize(); var shellSetting = _runningShellTable.Match(httpContext); // Register the shell settings as a custom feature. httpContext.Features.Set(shellSetting); // We only serve the next request if the tenant has been resolved. if (shellSetting != null) { var shellContext = _orchardHost.GetOrCreateShellContext(shellSetting); using (var scope = shellContext.CreateServiceScope()) { httpContext.RequestServices = scope.ServiceProvider; if (!shellContext.IsActivated) { lock (shellContext) { // The tenant gets activated here if (!shellContext.IsActivated) { var tenantEvents = scope.ServiceProvider .GetServices <IModularTenantEvents>(); foreach (var tenantEvent in tenantEvents) { tenantEvent.ActivatingAsync().Wait(); } httpContext.Items["BuildPipeline"] = true; shellContext.IsActivated = true; foreach (var tenantEvent in tenantEvents) { tenantEvent.ActivatedAsync().Wait(); } } } } await _next.Invoke(httpContext); } } }
public async Task Invoke(HttpContext httpContext) { // Ensure all ShellContext are loaded and available. _orchardHost.Initialize(); var shellSettings = _runningShellTable.Match(httpContext); // We only serve the next request if the tenant has been resolved. if (shellSettings != null) { var shellContext = _orchardHost.GetOrCreateShellContext(shellSettings); var hasPendingTasks = false; using (var scope = shellContext.EnterServiceScope()) { // Register the shell context as a custom feature. httpContext.Features.Set(shellContext); if (!shellContext.IsActivated) { var semaphore = _semaphores.GetOrAdd(shellSettings.Name, (name) => new SemaphoreSlim(1)); await semaphore.WaitAsync(); try { // The tenant gets activated here if (!shellContext.IsActivated) { using (var activatingScope = shellContext.EnterServiceScope()) { var tenantEvents = activatingScope.ServiceProvider.GetServices <IModularTenantEvents>(); foreach (var tenantEvent in tenantEvents) { await tenantEvent.ActivatingAsync(); } httpContext.Items["BuildPipeline"] = true; foreach (var tenantEvent in tenantEvents.Reverse()) { await tenantEvent.ActivatedAsync(); } } shellContext.IsActivated = true; } } finally { semaphore.Release(); _semaphores.TryRemove(shellSettings.Name, out semaphore); } } await _next.Invoke(httpContext); var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>(); hasPendingTasks = deferredTaskEngine?.HasPendingTasks ?? false; } // Create a new scope only if there are pending tasks if (hasPendingTasks) { shellContext = _orchardHost.GetOrCreateShellContext(shellSettings); using (var scope = shellContext.EnterServiceScope()) { var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>(); var context = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(context); } } } }