Example #1
0
        /// <summary>
        /// Sets the current <see cref="Circuits.Circuit"/>.
        /// </summary>
        /// <param name="circuitHost">The <see cref="Circuits.Circuit"/>.</param>
        /// <remarks>
        /// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store the circuit
        /// and other related values such as the <see cref="IJSRuntime"/> and <see cref="Renderer"/>
        /// in the local execution context. Application code should not need to call this method,
        /// it is primarily used by the Server-Side Components infrastructure.
        /// </remarks>
        public static void SetCurrentCircuitHost(CircuitHost circuitHost)
        {
            _current.Value = circuitHost ?? throw new ArgumentNullException(nameof(circuitHost));

            Microsoft.JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime);
            RendererRegistry.SetCurrentRendererRegistry(circuitHost.RendererRegistry);
        }
        public override CircuitHost CreateCircuitHost(HttpContext httpContext, IClientProxy client)
        {
            if (!_options.StartupActions.TryGetValue(httpContext.Request.Path, out var config))
            {
                var message = $"Could not find an ASP.NET Core Components startup action for request path '{httpContext.Request.Path}'.";
                throw new InvalidOperationException(message);
            }

            var scope                  = _scopeFactory.CreateScope();
            var jsRuntime              = new RemoteJSRuntime(client);
            var rendererRegistry       = new RendererRegistry();
            var synchronizationContext = new CircuitSynchronizationContext();
            var renderer               = new RemoteRenderer(scope.ServiceProvider, rendererRegistry, jsRuntime, client, synchronizationContext);

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                scope,
                client,
                rendererRegistry,
                renderer,
                config,
                jsRuntime,
                synchronizationContext,
                circuitHandlers);

            // Initialize per-circuit data that services need
            (circuitHost.Services.GetRequiredService <IJSRuntimeAccessor>() as DefaultJSRuntimeAccessor).JSRuntime = jsRuntime;
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit       = circuitHost.Circuit;

            return(circuitHost);
        }
Example #3
0
        public void Dispose_DisposesResources()
        {
            // Arrange
            var serviceScope   = new Mock <IServiceScope>();
            var clientProxy    = Mock.Of <IClientProxy>();
            var renderRegistry = new RendererRegistry();
            var jsRuntime      = Mock.Of <IJSRuntime>();
            var syncContext    = new CircuitSynchronizationContext();

            var remoteRenderer = new TestRemoteRenderer(
                Mock.Of <IServiceProvider>(),
                renderRegistry,
                jsRuntime,
                clientProxy,
                syncContext);

            var circuitHost = new CircuitHost(serviceScope.Object, clientProxy, renderRegistry, remoteRenderer, configure: _ => { }, jsRuntime: jsRuntime, synchronizationContext: syncContext);

            // Act
            circuitHost.Dispose();

            // Assert
            serviceScope.Verify(s => s.Dispose(), Times.Once());
            Assert.True(remoteRenderer.Disposed);
        }
 /// <summary>
 /// Registers an active <see cref="CircuitHost"/> with the register.
 /// </summary>
 public void Register(CircuitHost circuitHost)
 {
     if (!ConnectedCircuits.TryAdd(circuitHost.CircuitId, circuitHost))
     {
         // This will likely never happen, except perhaps in unit tests, since CircuitIds are unique.
         throw new ArgumentException($"Circuit with identity {circuitHost.CircuitId} is already registered.");
     }
 }
Example #5
0
 public void PermanentDisconnect(CircuitHost circuitHost)
 {
     if (ConnectedCircuits.TryRemove(circuitHost.CircuitId, out _))
     {
         Log.CircuitDisconnectedPermanently(_logger, circuitHost.CircuitId);
         circuitHost.Client.SetDisconnected();
     }
 }
        public override CircuitHost CreateCircuitHost(
            HttpContext httpContext,
            CircuitClientProxy client,
            string uriAbsolute,
            string baseUriAbsolute)
        {
            var components = ResolveComponentMetadata(httpContext, client);

            var scope            = _scopeFactory.CreateScope();
            var encoder          = scope.ServiceProvider.GetRequiredService <HtmlEncoder>();
            var jsRuntime        = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>();
            var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>();

            jsRuntime.Initialize(client);
            componentContext.Initialize(client);

            var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService <IUriHelper>();

            if (client != CircuitClientProxy.OfflineClient)
            {
                uriHelper.Initialize(uriAbsolute, baseUriAbsolute, jsRuntime);
            }
            else
            {
                uriHelper.Initialize(uriAbsolute, baseUriAbsolute);
            }

            var rendererRegistry = new RendererRegistry();
            var dispatcher       = Renderer.CreateDefaultDispatcher();
            var renderer         = new RemoteRenderer(
                scope.ServiceProvider,
                rendererRegistry,
                jsRuntime,
                client,
                dispatcher,
                encoder,
                _loggerFactory.CreateLogger <RemoteRenderer>());

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                scope,
                client,
                rendererRegistry,
                renderer,
                components,
                dispatcher,
                jsRuntime,
                circuitHandlers,
                _loggerFactory.CreateLogger <CircuitHost>());

            // Initialize per - circuit data that services need
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;

            return(circuitHost);
        }
Example #7
0
        public CircuitHost CreateCircuitHost(
            IReadOnlyList <ComponentDescriptor> components,
            CircuitClientProxy client,
            string baseUri,
            string uri,
            ClaimsPrincipal user)
        {
            var scope     = _scopeFactory.CreateScope();
            var jsRuntime = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>();

            jsRuntime.Initialize(client);

            var navigationManager      = (RemoteNavigationManager)scope.ServiceProvider.GetRequiredService <NavigationManager>();
            var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService <INavigationInterception>();

            if (client.Connected)
            {
                navigationManager.AttachJsRuntime(jsRuntime);
                navigationManager.Initialize(baseUri, uri);

                navigationInterception.AttachJSRuntime(jsRuntime);
            }
            else
            {
                navigationManager.Initialize(baseUri, uri);
            }

            var renderer = new RemoteRenderer(
                scope.ServiceProvider,
                _loggerFactory,
                _options,
                client,
                _loggerFactory.CreateLogger <RemoteRenderer>(),
                jsRuntime.ElementReferenceContext);

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                _circuitIdFactory.CreateCircuitId(),
                scope,
                _options,
                client,
                renderer,
                components,
                jsRuntime,
                circuitHandlers,
                _loggerFactory.CreateLogger <CircuitHost>());

            Log.CreatedCircuit(_logger, circuitHost);

            // Initialize per - circuit data that services need
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;
            circuitHost.SetCircuitUser(user);

            return(circuitHost);
        }
Example #8
0
        /// <summary>
        /// Sets the current <see cref="Circuits.Circuit"/>.
        /// </summary>
        /// <param name="circuitHost">The <see cref="Circuits.Circuit"/>.</param>
        /// <remarks>
        /// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store related values such as the
        /// <see cref="IJSRuntime"/> and <see cref="Renderer"/>
        /// in the local execution context. Application code should not need to call this method,
        /// it is primarily used by the Server-Side Components infrastructure.
        /// </remarks>
        public static void SetCurrentCircuitHost(CircuitHost circuitHost)
        {
            if (circuitHost is null)
            {
                throw new ArgumentNullException(nameof(circuitHost));
            }

            JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime);
        }
        public virtual Task DisconnectAsync(CircuitHost circuitHost, string connectionId)
        {
            Task circuitHandlerTask;

            lock (CircuitRegistryLock)
            {
                if (DisconnectCore(circuitHost, connectionId))
                {
                    circuitHandlerTask = circuitHost.Dispatcher.InvokeAsync(() => circuitHost.OnConnectionDownAsync(default));
Example #10
0
            protected override bool DisconnectCore(CircuitHost circuitHost, string connectionId)
            {
                if (BeforeDisconnect != null)
                {
                    Assert.True(BeforeDisconnect?.Wait(TimeSpan.FromSeconds(10)), "BeforeDisconnect failed to be set");
                }

                return(base.DisconnectCore(circuitHost, connectionId));
            }
 internal static void CreatedCircuit(ILogger logger, CircuitHost circuitHost)
 {
     if (circuitHost.Client.Connected)
     {
         _createdConnectedCircuit(logger, circuitHost.CircuitId, circuitHost.Client.ConnectionId, null);
     }
     else
     {
         _createdDisconnectedCircuit(logger, circuitHost.CircuitId, null);
     }
 }
Example #12
0
        public virtual Task DisconnectAsync(CircuitHost circuitHost, string connectionId)
        {
            Log.CircuitDisconnectStarted(_logger, circuitHost.CircuitId, connectionId);

            Task circuitHandlerTask;

            lock (CircuitRegistryLock)
            {
                if (DisconnectCore(circuitHost, connectionId))
                {
                    circuitHandlerTask = circuitHost.Renderer.Dispatcher.InvokeAsync(() => circuitHost.OnConnectionDownAsync(default));
Example #13
0
        /// <summary>
        /// Registers an active <see cref="CircuitHost"/> with the register.
        /// </summary>
        public void Register(CircuitHost circuitHost)
        {
            if (!ConnectedCircuits.TryAdd(circuitHost.CircuitId, circuitHost))
            {
                // This will likely never happen, except perhaps in unit tests, since CircuitIds are unique.
                throw new ArgumentException($"Circuit with identity {circuitHost.CircuitId} is already registered.");
            }

            // Register for unhandled exceptions from the circuit. The registry is responsible for tearing
            // down the circuit on errors.
            circuitHost.UnhandledException += CircuitHost_UnhandledException;
        }
Example #14
0
 private static async Task CleanupCircuitState(HttpContext context, CircuitNavigationStatus navigationStatus, CircuitHost circuitHost)
 {
     navigationStatus.Navigated = true;
     context.Items.Remove(CircuitHostKey);
     await circuitHost.DisposeAsync();
 }
Example #15
0
        public override CircuitHost CreateCircuitHost(
            HttpContext httpContext,
            CircuitClientProxy client,
            string uriAbsolute,
            string baseUriAbsolute,
            ClaimsPrincipal user)
        {
            var components = ResolveComponentMetadata(httpContext, client);

            var scope            = _scopeFactory.CreateScope();
            var encoder          = scope.ServiceProvider.GetRequiredService <HtmlEncoder>();
            var jsRuntime        = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>();
            var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>();

            jsRuntime.Initialize(client);
            componentContext.Initialize(client);

            var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService <IUriHelper>();
            var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService <INavigationInterception>();

            if (client.Connected)
            {
                uriHelper.AttachJsRuntime(jsRuntime);
                uriHelper.InitializeState(
                    uriAbsolute,
                    baseUriAbsolute);

                navigationInterception.AttachJSRuntime(jsRuntime);
            }
            else
            {
                uriHelper.InitializeState(uriAbsolute, baseUriAbsolute);
            }

            var rendererRegistry = new RendererRegistry();
            var renderer         = new RemoteRenderer(
                scope.ServiceProvider,
                _loggerFactory,
                rendererRegistry,
                jsRuntime,
                client,
                encoder,
                _loggerFactory.CreateLogger <RemoteRenderer>());

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                _circuitIdFactory.CreateCircuitId(),
                scope,
                client,
                rendererRegistry,
                renderer,
                components,
                jsRuntime,
                circuitHandlers,
                _loggerFactory.CreateLogger <CircuitHost>());

            Log.CreatedCircuit(_logger, circuitHost);

            // Initialize per - circuit data that services need
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;
            circuitHost.SetCircuitUser(user);

            return(circuitHost);
        }
Example #16
0
 internal static void CreatedCircuit(ILogger logger, CircuitHost circuitHost) =>
 _createdCircuit(logger, circuitHost.CircuitId.Id, circuitHost.Client.ConnectionId, null);
Example #17
0
 private static async Task CleanupCircuitState(HttpContext context, PrerenderingCancellationStatus cancellationStatus, CircuitHost circuitHost)
 {
     cancellationStatus.Canceled = true;
     context.Items.Remove(CircuitHostKey);
     await circuitHost.DisposeAsync();
 }
Example #18
0
 internal Circuit(CircuitHost circuitHost)
 {
     JSRuntime = circuitHost.JSRuntime;
     Services  = circuitHost.Services;
 }
Example #19
0
        public override CircuitHost CreateCircuitHost(
            HttpContext httpContext,
            CircuitClientProxy client,
            string uriAbsolute,
            string baseUriAbsolute)
        {
            var components = ResolveComponentMetadata(httpContext, client);

            var scope            = _scopeFactory.CreateScope();
            var encoder          = scope.ServiceProvider.GetRequiredService <HtmlEncoder>();
            var jsRuntime        = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>();
            var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>();

            jsRuntime.Initialize(client);
            componentContext.Initialize(client);

            // You can replace the AuthenticationStateProvider with a custom one, but in that case initialization is up to you
            var authenticationStateProvider = scope.ServiceProvider.GetService <AuthenticationStateProvider>();

            (authenticationStateProvider as FixedAuthenticationStateProvider)?.Initialize(httpContext.User);

            var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService <IUriHelper>();

            if (client.Connected)
            {
                uriHelper.AttachJsRuntime(jsRuntime);
                uriHelper.InitializeState(
                    uriAbsolute,
                    baseUriAbsolute);
            }
            else
            {
                uriHelper.InitializeState(uriAbsolute, baseUriAbsolute);
            }

            var rendererRegistry = new RendererRegistry();
            var dispatcher       = Renderer.CreateDefaultDispatcher();
            var renderer         = new RemoteRenderer(
                scope.ServiceProvider,
                rendererRegistry,
                jsRuntime,
                client,
                dispatcher,
                encoder,
                _loggerFactory.CreateLogger <RemoteRenderer>());

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                scope,
                client,
                rendererRegistry,
                renderer,
                components,
                dispatcher,
                jsRuntime,
                circuitHandlers,
                _loggerFactory.CreateLogger <CircuitHost>());

            // Initialize per - circuit data that services need
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;

            return(circuitHost);
        }
        public override CircuitHost CreateCircuitHost(
            HttpContext httpContext,
            CircuitClientProxy client,
            string baseUri,
            string uri,
            ClaimsPrincipal user)
        {
            // We do as much intialization as possible eagerly in this method, which makes the error handling
            // story much simpler. If we throw from here, it's handled inside the initial hub method.
            var components = ResolveComponentMetadata(httpContext, client);

            var scope            = _scopeFactory.CreateScope();
            var encoder          = scope.ServiceProvider.GetRequiredService <HtmlEncoder>();
            var jsRuntime        = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService <IJSRuntime>();
            var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService <IComponentContext>();

            jsRuntime.Initialize(client);
            componentContext.Initialize(client);

            var navigationManager      = (RemoteNavigationManager)scope.ServiceProvider.GetRequiredService <NavigationManager>();
            var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService <INavigationInterception>();

            if (client.Connected)
            {
                navigationManager.AttachJsRuntime(jsRuntime);
                navigationManager.Initialize(baseUri, uri);

                navigationInterception.AttachJSRuntime(jsRuntime);
            }
            else
            {
                navigationManager.Initialize(baseUri, uri);
            }

            var renderer = new RemoteRenderer(
                scope.ServiceProvider,
                _loggerFactory,
                _options,
                jsRuntime,
                client,
                encoder,
                _loggerFactory.CreateLogger <RemoteRenderer>());

            var circuitHandlers = scope.ServiceProvider.GetServices <CircuitHandler>()
                                  .OrderBy(h => h.Order)
                                  .ToArray();

            var circuitHost = new CircuitHost(
                _circuitIdFactory.CreateCircuitId(),
                scope,
                client,
                renderer,
                components,
                jsRuntime,
                circuitHandlers,
                _loggerFactory.CreateLogger <CircuitHost>());

            Log.CreatedCircuit(_logger, circuitHost);

            // Initialize per - circuit data that services need
            (circuitHost.Services.GetRequiredService <ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;
            circuitHost.SetCircuitUser(user);

            return(circuitHost);
        }
Example #21
0
 public void SetCircuit(IDictionary <object, object?> circuitHandles, object circuitKey, CircuitHost circuitHost)
 {
     circuitHandles[circuitKey] = circuitHost?.Handle;
 }