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;
                }
            }
        }
Esempio n. 2
0
        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);
                }
            }
        }
Esempio n. 3
0
        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);
                    }
                }
            }
        }