├── .editorconfig ├── .gitignore ├── Fluxera.Extensions.Hosting.sln ├── GitVersion.yml ├── LICENSE ├── README.md ├── azure-pipelines.yml ├── icon.png ├── samples ├── BlazorApp1 │ ├── App.razor │ ├── BlazorApp1.csproj │ ├── BlazorApp1Host.cs │ ├── BlazorApp1Module.cs │ ├── Layout │ │ ├── MainLayout.razor │ │ ├── MainLayout.razor.css │ │ ├── NavMenu.razor │ │ └── NavMenu.razor.css │ ├── Pages │ │ ├── Counter.razor │ │ ├── Home.razor │ │ └── Weather.razor │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── _Imports.razor │ └── wwwroot │ │ ├── css │ │ ├── app.css │ │ └── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── favicon.png │ │ ├── icon-192.png │ │ ├── index.html │ │ └── sample-data │ │ └── weather.json ├── BlazorApp2 │ ├── BlazorApp2.Client │ │ ├── BlazorApp2.Client.csproj │ │ ├── BlazorApp2Host.cs │ │ ├── BlazorApp2Module.cs │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ ├── MainLayout.razor.css │ │ │ ├── NavMenu.razor │ │ │ └── NavMenu.razor.css │ │ ├── Pages │ │ │ ├── Counter.razor │ │ │ ├── Home.razor │ │ │ └── Weather.razor │ │ ├── Program.cs │ │ ├── Routes.razor │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ └── BlazorApp2 │ │ ├── BlazorApp2.csproj │ │ ├── Components │ │ ├── App.razor │ │ ├── Pages │ │ │ └── Error.razor │ │ └── _Imports.razor │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── app.css │ │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ └── favicon.png ├── ConsoleApp1 │ ├── ConsoleApp1.csproj │ ├── ConsoleApp1Host.cs │ ├── ConsoleApp1Module.cs │ ├── ConsoleHostedService.cs │ ├── IWeatherService.cs │ ├── Program.cs │ ├── WeatherService.cs │ ├── WeatherSettings.cs │ └── appsettings.json ├── Directory.Build.props ├── MauiApp1 │ ├── App.xaml │ ├── App.xaml.cs │ ├── AppShell.xaml │ ├── AppShell.xaml.cs │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── MauiApp1.csproj │ ├── MauiApp1Host.cs │ ├── MauiApp1Module.cs │ ├── MauiProgram.cs │ ├── Platforms │ │ ├── Android │ │ │ ├── AndroidManifest.xml │ │ │ ├── MainActivity.cs │ │ │ ├── MainApplication.cs │ │ │ └── Resources │ │ │ │ └── values │ │ │ │ └── colors.xml │ │ ├── MacCatalyst │ │ │ ├── AppDelegate.cs │ │ │ ├── Entitlements.plist │ │ │ ├── Info.plist │ │ │ └── Program.cs │ │ ├── Tizen │ │ │ ├── Main.cs │ │ │ └── tizen-manifest.xml │ │ ├── Windows │ │ │ ├── App.xaml │ │ │ ├── App.xaml.cs │ │ │ ├── Package.appxmanifest │ │ │ └── app.manifest │ │ └── iOS │ │ │ ├── AppDelegate.cs │ │ │ ├── Info.plist │ │ │ └── Program.cs │ ├── Properties │ │ └── launchSettings.json │ └── Resources │ │ ├── AppIcon │ │ ├── appicon.svg │ │ └── appiconfg.svg │ │ ├── Fonts │ │ ├── OpenSans-Regular.ttf │ │ └── OpenSans-Semibold.ttf │ │ ├── Images │ │ └── dotnet_bot.png │ │ ├── Raw │ │ └── AboutAssets.txt │ │ ├── Splash │ │ └── splash.svg │ │ └── Styles │ │ ├── Colors.xaml │ │ └── Styles.xaml ├── Samples.sln ├── TestProject1 │ ├── TestApplication1Host.cs │ ├── TestProject1.csproj │ └── Tests.cs ├── WebApplication1 │ ├── Controllers │ │ └── WeatherForecastController.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── WeatherForecast.cs │ ├── WebApplication1.csproj │ ├── WebApplication1Host.cs │ ├── WebApplication1Module.cs │ ├── appsettings.Development.json │ └── appsettings.json └── WpfApp1 │ ├── AssemblyInfo.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── Program.cs │ ├── WpfApp1.csproj │ ├── WpfApp1Host.cs │ ├── WpfApp1Module.cs │ └── appsettings.json ├── src ├── .gitkeep ├── Directory.Build.props ├── Fluxera.Extensions.Hosting.Abstractions │ ├── ApplicationLoaderBuilderFunc.cs │ ├── DependsOnAttribute.cs │ ├── Fluxera.Extensions.Hosting.Abstractions.csproj │ ├── IApplicationHost.cs │ ├── IApplicationInitializationContext.cs │ ├── IApplicationLoader.cs │ ├── IApplicationLoaderInitializationContext.cs │ ├── IApplicationShutdownContext.cs │ ├── ILoggingContext.cs │ ├── IModularApplicationBuilder.cs │ ├── IServiceConfigurationContext.cs │ ├── Modules │ │ ├── ConfigureApplicationModule.cs │ │ ├── ConfigureServicesModule.cs │ │ ├── IConfigureApplication.cs │ │ ├── IConfigureConfigureApplicationModule.cs │ │ ├── IConfigureServices.cs │ │ ├── IConfigureServicesModule.cs │ │ ├── IModule.cs │ │ ├── IModuleContainer.cs │ │ ├── IModuleDescriptor.cs │ │ ├── IModuleLifecycleContributor.cs │ │ ├── IModuleLoader.cs │ │ ├── IModuleManager.cs │ │ ├── IPostConfigureApplication.cs │ │ ├── IPostConfigureServices.cs │ │ ├── IPreConfigureApplication.cs │ │ ├── IPreConfigureServices.cs │ │ └── IShutdownApplicationModule.cs │ ├── ObjectAccessorLifetime.cs │ └── Plugins │ │ ├── IPluginConfigurationContext.cs │ │ ├── IPluginSource.cs │ │ └── IPluginSourceList.cs ├── Fluxera.Extensions.Hosting.AspNetCore.TestHost │ ├── Fluxera.Extensions.Hosting.AspNetCore.TestHost.csproj │ ├── ITestApplicationHost.cs │ ├── TestApplicationHost.cs │ └── WebHostBuilderExtensions.cs ├── Fluxera.Extensions.Hosting.AspNetCore │ ├── ApplicationInitializationContextExtensions.cs │ ├── ApplicationLoaderBuilderFuncFactory.cs │ ├── Fluxera.Extensions.Hosting.AspNetCore.csproj │ ├── ServiceCollectionExtensions.cs │ ├── WebApplicationHost.cs │ ├── WebApplicationInitializationContext.cs │ ├── WebApplicationLoader.cs │ └── WebApplicationLoaderInitializationContext.cs ├── Fluxera.Extensions.Hosting.Blazor │ ├── BlazorApplicationHost`1.cs │ ├── BlazorApplicationHost`2.cs │ ├── ConsoleOutLogger.cs │ ├── ConsoleOutLoggerFactory.cs │ ├── ConsoleOutLoggerProvider.cs │ ├── Fluxera.Extensions.Hosting.Blazor.csproj │ ├── WebAssemblyHostBuilderExtensions.cs │ └── WebAssemblyLifetime.cs ├── Fluxera.Extensions.Hosting.Console │ ├── ConsoleApplicationHost.cs │ └── Fluxera.Extensions.Hosting.Console.csproj ├── Fluxera.Extensions.Hosting.Maui │ ├── Fluxera.Extensions.Hosting.Maui.csproj │ ├── IMauiApplicationHost.cs │ ├── MauiAppBuilderExtensions.cs │ └── MauiApplicationHost.cs ├── Fluxera.Extensions.Hosting.WindowsService │ ├── Fluxera.Extensions.Hosting.WindowsService.csproj │ └── WindowsServiceApplicationHost.cs ├── Fluxera.Extensions.Hosting.Wpf │ ├── ApplicationExtensions.cs │ ├── DictionaryExtensions.cs │ ├── Fluxera.Extensions.Hosting.Wpf.csproj │ ├── HostBuilderExtensions.cs │ ├── IMainWindow.cs │ ├── IWpfApplicationInitializer.cs │ ├── LoggerExtensions.cs │ ├── WpfApplicationHost.cs │ ├── WpfApplicationLifetime.cs │ ├── WpfApplicationLifetimeOptions.cs │ └── WpfContext.cs └── Fluxera.Extensions.Hosting │ ├── ApplicationHost.cs │ ├── ApplicationHostEvents.cs │ ├── ApplicationInitializationContext.cs │ ├── ApplicationLoader.cs │ ├── ApplicationLoaderInitializationContext.cs │ ├── ApplicationShutdownContext.cs │ ├── CollectionExtensions.cs │ ├── DependenciesListExtensions.cs │ ├── Fluxera.Extensions.Hosting.csproj │ ├── Guard.cs │ ├── HostBuilderExtensions.cs │ ├── HostEnvironmentExtensions.cs │ ├── HostInitializationFailedEventArgs.cs │ ├── LoggerExtensions.cs │ ├── LoggingContextExtensions.cs │ ├── ModularApplicationBuilder.cs │ ├── ModuleHelper.cs │ ├── ModuleLifecycleContributorBase.cs │ ├── ModuleLoaderExtensions.cs │ ├── Modules │ ├── ModuleDescriptor.cs │ ├── ModuleLoader.cs │ ├── ModuleManager.cs │ ├── OnApplicationInitializationModuleLifecycleContributor.cs │ ├── OnApplicationShutdownModuleLifecycleContributor.cs │ ├── OnPostApplicationInitializationModuleLifecycleContributor.cs │ └── OnPreApplicationInitializationModuleLifecycleContributor.cs │ ├── NumericExtensions.cs │ ├── PluginConfigurationContext.cs │ ├── PluginConfigurationContextExtensions.cs │ ├── Plugins │ ├── FolderPluginSource.cs │ ├── PluginModuleTypeSource.cs │ ├── PluginSourceExtensions.cs │ ├── PluginSourceList.cs │ └── PluginTypeListSource.cs │ ├── ServiceCollectionExtensions.cs │ └── ServiceConfigurationContext.cs └── tests ├── .gitkeep ├── Directory.Build.props └── Fluxera.Extensions.Hosting.UnitTests ├── ApplicationLoaderServicesTests.cs ├── DependsOn ├── DependsOnAttributeTests.cs └── Modules │ ├── DependsOnThirdModule.cs │ ├── FirstModule.cs │ ├── RootModule.cs │ ├── SecondModule.cs │ └── ThirdModule.cs ├── Fluxera.Extensions.Hosting.UnitTests.csproj ├── GenericApplicationModule.cs ├── HostingGenericModuleTests.cs ├── HostingModuleTests.cs ├── ServiceCollectionTests.cs ├── StartupModuleTestBase.cs ├── TestApplicationLifetime.cs ├── TestBase.cs ├── TestConfigureApplicationModule.cs └── TestLifetime.cs /GitVersion.yml: -------------------------------------------------------------------------------- 1 | next-version: 9.0.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2023 Fluxera Software Development GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluxera/Fluxera.Extensions.Hosting/edb8d919e2a09af1c398dc8a2576790a3e9c689c/icon.png -------------------------------------------------------------------------------- /samples/BlazorApp1/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Not found 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /samples/BlazorApp1/BlazorApp1.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/BlazorApp1/BlazorApp1Host.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp1 2 | { 3 | using Fluxera.Extensions.Hosting; 4 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 5 | using Microsoft.Extensions.Logging; 6 | using Serilog; 7 | using Serilog.Core; 8 | using Serilog.Extensions.Logging; 9 | 10 | internal sealed class BlazorApp1Host : BlazorApplicationHost 11 | { 12 | /// 13 | protected override void ConfigureHostBuilder(WebAssemblyHostBuilder builder) 14 | { 15 | base.ConfigureHostBuilder(builder); 16 | 17 | // Use Serilog as default logger. 18 | // https://github.com/serilog/serilog-sinks-browserconsole 19 | Logger logger = new LoggerConfiguration() 20 | .MinimumLevel.Verbose() 21 | .WriteTo.BrowserConsole() 22 | .CreateLogger(); 23 | 24 | builder.Logging.AddSerilog(logger); 25 | } 26 | 27 | /// 28 | protected override ILoggerFactory CreateBootstrapperLoggerFactory() 29 | { 30 | // https://github.com/serilog/serilog-sinks-browserconsole 31 | Logger bootstrapLogger = new LoggerConfiguration() 32 | .MinimumLevel.Debug() 33 | .WriteTo.BrowserConsole() 34 | .CreateLogger(); 35 | 36 | ILoggerFactory loggerFactory = new SerilogLoggerFactory(bootstrapLogger); 37 | return loggerFactory; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samples/BlazorApp1/BlazorApp1Module.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp1 2 | { 3 | using System; 4 | using System.Net.Http; 5 | using Fluxera.Extensions.DependencyInjection; 6 | using Fluxera.Extensions.Hosting; 7 | using Fluxera.Extensions.Hosting.Modules; 8 | using JetBrains.Annotations; 9 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | [PublicAPI] 13 | [UsedImplicitly] 14 | internal sealed class BlazorApp1Module : ConfigureServicesModule 15 | { 16 | /// 17 | public override void ConfigureServices(IServiceConfigurationContext context) 18 | { 19 | IWebAssemblyHostEnvironment hostEnvironment = context.Services.GetObject(); 20 | context.Services.AddScoped(_ => new HttpClient 21 | { 22 | BaseAddress = new Uri(hostEnvironment.BaseAddress) 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 |
3 | 6 | 7 |
8 |
9 | About 10 |
11 | 12 |
13 | @Body 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row ::deep .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | text-decoration: none; 28 | } 29 | 30 | .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | .top-row ::deep a:first-child { 35 | overflow: hidden; 36 | text-overflow: ellipsis; 37 | } 38 | 39 | @media (max-width: 640.98px) { 40 | .top-row { 41 | justify-content: space-between; 42 | } 43 | 44 | .top-row ::deep a, .top-row ::deep .btn-link { 45 | margin-left: 0; 46 | } 47 | } 48 | 49 | @media (min-width: 641px) { 50 | .page { 51 | flex-direction: row; 52 | } 53 | 54 | .sidebar { 55 | width: 250px; 56 | height: 100vh; 57 | position: sticky; 58 | top: 0; 59 | } 60 | 61 | .top-row { 62 | position: sticky; 63 | top: 0; 64 | z-index: 1; 65 | } 66 | 67 | .top-row.auth ::deep a:first-child { 68 | flex: 1; 69 | text-align: right; 70 | width: 0; 71 | } 72 | 73 | .top-row, article { 74 | padding-left: 2rem !important; 75 | padding-right: 1.5rem !important; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Layout/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  9 | 10 | 29 | 30 | @code { 31 | private bool collapseNavMenu = true; 32 | 33 | private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; 34 | 35 | private void ToggleNavMenu() 36 | { 37 | collapseNavMenu = !collapseNavMenu; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Pages/Counter.razor: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 | 3 | Counter 4 | 5 |

Counter

6 | 7 |

Current count: @currentCount

8 | 9 | 10 | 11 | @code { 12 | private int currentCount = 0; 13 | 14 | private void IncrementCount() 15 | { 16 | currentCount++; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Pages/Home.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | Home 4 | 5 |

Hello, world!

6 | 7 | Welcome to your new app. 8 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Pages/Weather.razor: -------------------------------------------------------------------------------- 1 | @page "/weather" 2 | @inject HttpClient Http 3 | 4 | Weather 5 | 6 |

Weather

7 | 8 |

This component demonstrates fetching data from the server.

9 | 10 | @if (forecasts == null) 11 | { 12 |

Loading...

13 | } 14 | else 15 | { 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | @foreach (var forecast in forecasts) 27 | { 28 | 29 | 30 | 31 | 32 | 33 | 34 | } 35 | 36 |
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
37 | } 38 | 39 | @code { 40 | private WeatherForecast[]? forecasts; 41 | 42 | protected override async Task OnInitializedAsync() 43 | { 44 | forecasts = await Http.GetFromJsonAsync("sample-data/weather.json"); 45 | } 46 | 47 | public class WeatherForecast 48 | { 49 | public DateOnly Date { get; set; } 50 | 51 | public int TemperatureC { get; set; } 52 | 53 | public string? Summary { get; set; } 54 | 55 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Program.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp1 2 | { 3 | using System.Threading.Tasks; 4 | using Fluxera.Extensions.Hosting; 5 | 6 | public static class Program 7 | { 8 | public static async Task Main(string[] args) 9 | { 10 | await ApplicationHost.RunAsync(args); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/BlazorApp1/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:24422", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "BlazorApp1": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 16 | "applicationUrl": "http://localhost:5108", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /samples/BlazorApp1/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 8 | @using Microsoft.JSInterop 9 | @using BlazorApp1 10 | @using BlazorApp1.Layout 11 | -------------------------------------------------------------------------------- /samples/BlazorApp1/wwwroot/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluxera/Fluxera.Extensions.Hosting/edb8d919e2a09af1c398dc8a2576790a3e9c689c/samples/BlazorApp1/wwwroot/favicon.png -------------------------------------------------------------------------------- /samples/BlazorApp1/wwwroot/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluxera/Fluxera.Extensions.Hosting/edb8d919e2a09af1c398dc8a2576790a3e9c689c/samples/BlazorApp1/wwwroot/icon-192.png -------------------------------------------------------------------------------- /samples/BlazorApp1/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | BlazorApp1 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 |
25 | An unhandled error has occurred. 26 | Reload 27 | 🗙 28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /samples/BlazorApp1/wwwroot/sample-data/weather.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "date": "2022-01-06", 4 | "temperatureC": 1, 5 | "summary": "Freezing" 6 | }, 7 | { 8 | "date": "2022-01-07", 9 | "temperatureC": 14, 10 | "summary": "Bracing" 11 | }, 12 | { 13 | "date": "2022-01-08", 14 | "temperatureC": -13, 15 | "summary": "Freezing" 16 | }, 17 | { 18 | "date": "2022-01-09", 19 | "temperatureC": -16, 20 | "summary": "Balmy" 21 | }, 22 | { 23 | "date": "2022-01-10", 24 | "temperatureC": -2, 25 | "summary": "Chilly" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/BlazorApp2.Client.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | false 6 | true 7 | Default 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/BlazorApp2Host.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp2.Client 2 | { 3 | using Fluxera.Extensions.Hosting; 4 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 5 | using Microsoft.Extensions.Logging; 6 | using Serilog; 7 | using Serilog.Core; 8 | using Serilog.Extensions.Logging; 9 | 10 | internal sealed class BlazorApp2Host : BlazorApplicationHost 11 | { 12 | /// 13 | protected override void ConfigureHostBuilder(WebAssemblyHostBuilder builder) 14 | { 15 | base.ConfigureHostBuilder(builder); 16 | 17 | // Use Serilog as default logger. 18 | // https://github.com/serilog/serilog-sinks-browserconsole 19 | Logger logger = new LoggerConfiguration() 20 | .MinimumLevel.Verbose() 21 | .WriteTo.BrowserConsole() 22 | .CreateLogger(); 23 | 24 | builder.Logging.AddSerilog(logger); 25 | } 26 | 27 | /// 28 | protected override ILoggerFactory CreateBootstrapperLoggerFactory() 29 | { 30 | // https://github.com/serilog/serilog-sinks-browserconsole 31 | Logger bootstrapLogger = new LoggerConfiguration() 32 | .MinimumLevel.Debug() 33 | .WriteTo.BrowserConsole() 34 | .CreateLogger(); 35 | 36 | ILoggerFactory loggerFactory = new SerilogLoggerFactory(bootstrapLogger); 37 | return loggerFactory; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/BlazorApp2Module.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp2.Client 2 | { 3 | using System; 4 | using System.Net.Http; 5 | using Fluxera.Extensions.DependencyInjection; 6 | using Fluxera.Extensions.Hosting; 7 | using Fluxera.Extensions.Hosting.Modules; 8 | using JetBrains.Annotations; 9 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | [PublicAPI] 13 | [UsedImplicitly] 14 | internal sealed class BlazorApp2Module : ConfigureServicesModule 15 | { 16 | /// 17 | public override void ConfigureServices(IServiceConfigurationContext context) 18 | { 19 | IWebAssemblyHostEnvironment hostEnvironment = context.Services.GetObject(); 20 | context.Services.AddScoped(_ => new HttpClient 21 | { 22 | BaseAddress = new Uri(hostEnvironment.BaseAddress) 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 |
9 |
10 | About 11 |
12 | 13 |
14 | @Body 15 |
16 |
17 |
18 | 19 |
20 | An unhandled error has occurred. 21 | Reload 22 | 🗙 23 |
24 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row ::deep .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | text-decoration: none; 28 | } 29 | 30 | .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | .top-row ::deep a:first-child { 35 | overflow: hidden; 36 | text-overflow: ellipsis; 37 | } 38 | 39 | @media (max-width: 640.98px) { 40 | .top-row { 41 | justify-content: space-between; 42 | } 43 | 44 | .top-row ::deep a, .top-row ::deep .btn-link { 45 | margin-left: 0; 46 | } 47 | } 48 | 49 | @media (min-width: 641px) { 50 | .page { 51 | flex-direction: row; 52 | } 53 | 54 | .sidebar { 55 | width: 250px; 56 | height: 100vh; 57 | position: sticky; 58 | top: 0; 59 | } 60 | 61 | .top-row { 62 | position: sticky; 63 | top: 0; 64 | z-index: 1; 65 | } 66 | 67 | .top-row.auth ::deep a:first-child { 68 | flex: 1; 69 | text-align: right; 70 | width: 0; 71 | } 72 | 73 | .top-row, article { 74 | padding-left: 2rem !important; 75 | padding-right: 1.5rem !important; 76 | } 77 | } 78 | 79 | #blazor-error-ui { 80 | background: lightyellow; 81 | bottom: 0; 82 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 83 | display: none; 84 | left: 0; 85 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 86 | position: fixed; 87 | width: 100%; 88 | z-index: 1000; 89 | } 90 | 91 | #blazor-error-ui .dismiss { 92 | cursor: pointer; 93 | position: absolute; 94 | right: 0.75rem; 95 | top: 0.5rem; 96 | } 97 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Layout/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 30 | 31 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Pages/Counter.razor: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 | 3 | Counter 4 | 5 |

Counter

6 | 7 |

Current count: @currentCount

8 | 9 | 10 | 11 | @code { 12 | private int currentCount = 0; 13 | 14 | private void IncrementCount() 15 | { 16 | currentCount++; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Pages/Home.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | Home 4 | 5 |

Hello, world!

6 | 7 | Welcome to your new app. 8 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Pages/Weather.razor: -------------------------------------------------------------------------------- 1 | @page "/weather" 2 | 3 | Weather 4 | 5 |

Weather

6 | 7 |

This component demonstrates showing data.

8 | 9 | @if (forecasts == null) 10 | { 11 |

Loading...

12 | } 13 | else 14 | { 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | @foreach (var forecast in forecasts) 26 | { 27 | 28 | 29 | 30 | 31 | 32 | 33 | } 34 | 35 |
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
36 | } 37 | 38 | @code { 39 | private WeatherForecast[]? forecasts; 40 | 41 | protected override async Task OnInitializedAsync() 42 | { 43 | // Simulate asynchronous loading to demonstrate a loading indicator 44 | await Task.Delay(500); 45 | 46 | var startDate = DateOnly.FromDateTime(DateTime.Now); 47 | var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; 48 | forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast 49 | { 50 | Date = startDate.AddDays(index), 51 | TemperatureC = Random.Shared.Next(-20, 55), 52 | Summary = summaries[Random.Shared.Next(summaries.Length)] 53 | }).ToArray(); 54 | } 55 | 56 | private class WeatherForecast 57 | { 58 | public DateOnly Date { get; set; } 59 | public int TemperatureC { get; set; } 60 | public string? Summary { get; set; } 61 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Program.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp2.Client 2 | { 3 | using System.Threading.Tasks; 4 | using Fluxera.Extensions.Hosting; 5 | 6 | public static class Program 7 | { 8 | public static async Task Main(string[] args) 9 | { 10 | await ApplicationHost.RunAsync(args); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazorApp2.Client 10 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/wwwroot/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2.Client/wwwroot/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/BlazorApp2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/Components/Pages/Error.razor: -------------------------------------------------------------------------------- 1 | @page "/Error" 2 | @using System.Diagnostics 3 | @using Microsoft.AspNetCore.Http 4 | 5 | Error 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (ShowRequestId) 11 | { 12 |

13 | Request ID: @RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to Development environment will display more detailed information about the error that occurred. 20 |

21 |

22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

27 | 28 | @code{ 29 | [CascadingParameter] 30 | private HttpContext? HttpContext { get; set; } 31 | 32 | private string? RequestId { get; set; } 33 | private bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 34 | 35 | protected override void OnInitialized() => 36 | RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; 37 | } 38 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazorApp2 10 | @using BlazorApp2.Client 11 | @using BlazorApp2.Components 12 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/Program.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorApp2 2 | { 3 | using BlazorApp2.Client.Pages; 4 | using BlazorApp2.Components; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | 9 | public static class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | WebApplicationBuilder builder = WebApplication.CreateBuilder(args); 14 | 15 | // Add services to the container. 16 | builder.Services 17 | .AddRazorComponents() 18 | .AddInteractiveWebAssemblyComponents(); 19 | 20 | WebApplication app = builder.Build(); 21 | 22 | // Configure the HTTP request pipeline. 23 | if(app.Environment.IsDevelopment()) 24 | { 25 | app.UseWebAssemblyDebugging(); 26 | } 27 | else 28 | { 29 | app.UseExceptionHandler("/Error"); 30 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 31 | app.UseHsts(); 32 | } 33 | 34 | app.UseHttpsRedirection(); 35 | 36 | app.UseStaticFiles(); 37 | app.UseAntiforgery(); 38 | 39 | app.MapRazorComponents() 40 | .AddInteractiveWebAssemblyRenderMode() 41 | .AddAdditionalAssemblies(typeof(Counter).Assembly); 42 | 43 | app.Run(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:44051", 8 | "sslPort": 44326 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 17 | "applicationUrl": "http://localhost:5130", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 27 | "applicationUrl": "https://localhost:7243;http://localhost:5130", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/wwwroot/app.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 3 | } 4 | 5 | a, .btn-link { 6 | color: #006bb7; 7 | } 8 | 9 | .btn-primary { 10 | color: #fff; 11 | background-color: #1b6ec2; 12 | border-color: #1861ac; 13 | } 14 | 15 | .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { 16 | box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; 17 | } 18 | 19 | .content { 20 | padding-top: 1.1rem; 21 | } 22 | 23 | h1:focus { 24 | outline: none; 25 | } 26 | 27 | .valid.modified:not([type=checkbox]) { 28 | outline: 1px solid #26b050; 29 | } 30 | 31 | .invalid { 32 | outline: 1px solid #e50000; 33 | } 34 | 35 | .validation-message { 36 | color: #e50000; 37 | } 38 | 39 | .blazor-error-boundary { 40 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 41 | padding: 1rem 1rem 1rem 3.7rem; 42 | color: white; 43 | } 44 | 45 | .blazor-error-boundary::after { 46 | content: "An error has occurred." 47 | } 48 | 49 | .darker-border-checkbox.form-check-input { 50 | border-color: #929292; 51 | } 52 | -------------------------------------------------------------------------------- /samples/BlazorApp2/BlazorApp2/wwwroot/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluxera/Fluxera.Extensions.Hosting/edb8d919e2a09af1c398dc8a2576790a3e9c689c/samples/BlazorApp2/BlazorApp2/wwwroot/favicon.png -------------------------------------------------------------------------------- /samples/ConsoleApp1/ConsoleApp1.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | Exe 6 | false 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | true 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/ConsoleApp1Host.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using Autofac.Extensions.DependencyInjection; 4 | using Fluxera.Extensions.Hosting; 5 | using Fluxera.Extensions.Hosting.Plugins; 6 | using JetBrains.Annotations; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.Hosting; 9 | using Microsoft.Extensions.Logging; 10 | using Serilog; 11 | using Serilog.Extensions.Hosting; 12 | using Serilog.Extensions.Logging; 13 | 14 | [PublicAPI] 15 | [UsedImplicitly] 16 | internal sealed class ConsoleApp1Host : ConsoleApplicationHost // WindowsServiceApplicationHost 17 | { 18 | /// 19 | protected override void ConfigureApplicationPlugins(IPluginConfigurationContext context) 20 | { 21 | base.ConfigureApplicationPlugins(context); 22 | } 23 | 24 | /// 25 | protected override void ConfigureHostBuilder(IHostBuilder builder) 26 | { 27 | base.ConfigureHostBuilder(builder); 28 | 29 | // Use Autofac as default container. 30 | builder.UseServiceProviderFactory(new AutofacServiceProviderFactory()); 31 | 32 | // Use Serilog as default logger. 33 | builder.UseSerilog((context, services, configuration) => configuration 34 | .Enrich.FromLogContext() 35 | .WriteTo.Console() 36 | .WriteTo.OpenTelemetry() // https://github.com/serilog/serilog-sinks-opentelemetry 37 | .ReadFrom.Configuration(context.Configuration) 38 | .ReadFrom.Services(services)); 39 | } 40 | 41 | /// 42 | protected override ILoggerFactory CreateBootstrapperLoggerFactory(IConfiguration configuration) 43 | { 44 | ReloadableLogger bootstrapLogger = new LoggerConfiguration() 45 | .Enrich.FromLogContext() 46 | .WriteTo.Console() 47 | .WriteTo.OpenTelemetry() // https://github.com/serilog/serilog-sinks-opentelemetry 48 | .ReadFrom.Configuration(configuration) 49 | .CreateBootstrapLogger(); 50 | 51 | ILoggerFactory loggerFactory = new SerilogLoggerFactory(bootstrapLogger); 52 | return loggerFactory; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/ConsoleApp1Module.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using System.Globalization; 4 | using Fluxera.Extensions.Hosting; 5 | using Fluxera.Extensions.Hosting.Modules; 6 | using JetBrains.Annotations; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | [PublicAPI] 10 | [UsedImplicitly] 11 | internal sealed class ConsoleApp1Module : ConfigureApplicationModule 12 | { 13 | /// 14 | public override void ConfigureServices(IServiceConfigurationContext context) 15 | { 16 | CultureInfo.DefaultThreadCurrentCulture = CultureInfo.GetCultureInfo("de-DE"); 17 | CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo("de-DE"); 18 | 19 | context.Services.AddHostedService(); 20 | context.Services.AddSingleton(); 21 | context.Services.AddOptions().Bind(context.Configuration.GetSection("Weather")); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/ConsoleHostedService.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | internal sealed class ConsoleHostedService : IHostedService 11 | { 12 | private readonly IHostApplicationLifetime appLifetime; 13 | private readonly ILogger logger; 14 | private readonly IWeatherService weatherService; 15 | 16 | private int? exitCode; 17 | 18 | public ConsoleHostedService( 19 | ILogger logger, 20 | IHostApplicationLifetime appLifetime, 21 | IWeatherService weatherService) 22 | { 23 | this.logger = logger; 24 | this.appLifetime = appLifetime; 25 | this.weatherService = weatherService; 26 | } 27 | 28 | public Task StartAsync(CancellationToken cancellationToken) 29 | { 30 | this.logger.LogDebug($"Starting with arguments: {string.Join(" ", Environment.GetCommandLineArgs())}"); 31 | 32 | this.appLifetime.ApplicationStarted.Register(() => 33 | { 34 | Task.Run(async () => 35 | { 36 | try 37 | { 38 | IReadOnlyList temperatures = await this.weatherService.GetFiveDayTemperaturesAsync(); 39 | for(int i = 0; i < temperatures.Count; i++) 40 | { 41 | this.logger.LogInformation($"{DateTime.Today.AddDays(i).DayOfWeek}: {temperatures[i]}"); 42 | } 43 | 44 | this.exitCode = 0; 45 | } 46 | catch(Exception ex) 47 | { 48 | this.logger.LogError(ex, "Unhandled exception!"); 49 | this.exitCode = 1; 50 | } 51 | finally 52 | { 53 | // Stop the application once the work is done 54 | this.appLifetime.StopApplication(); 55 | } 56 | }, cancellationToken); 57 | }); 58 | 59 | return Task.CompletedTask; 60 | } 61 | 62 | public Task StopAsync(CancellationToken cancellationToken) 63 | { 64 | this.logger.LogDebug($"Exiting with return code: {this.exitCode}"); 65 | 66 | // Exit code may be null if the user cancelled via Ctrl+C/SIGTERM 67 | Environment.ExitCode = this.exitCode.GetValueOrDefault(-1); 68 | return Task.CompletedTask; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/IWeatherService.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | internal interface IWeatherService 7 | { 8 | Task> GetFiveDayTemperaturesAsync(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/Program.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | using Fluxera.Extensions.Hosting; 6 | 7 | public static class Program 8 | { 9 | public static async Task Main(string[] args) 10 | { 11 | await ApplicationHost.RunAsync(args); 12 | 13 | Console.WriteLine(); 14 | Console.WriteLine("Press any key to quit..."); 15 | Console.ReadKey(true); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/WeatherService.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Microsoft.Extensions.Options; 7 | 8 | internal sealed class WeatherService : IWeatherService 9 | { 10 | private readonly IOptions weatherSettings; 11 | 12 | public WeatherService(IOptions weatherSettings) 13 | { 14 | this.weatherSettings = weatherSettings; 15 | } 16 | 17 | public Task> GetFiveDayTemperaturesAsync() 18 | { 19 | int[] temperatures = { 76, 76, 77, 79, 78 }; 20 | if(this.weatherSettings.Value.Unit.Equals("C", StringComparison.OrdinalIgnoreCase)) 21 | { 22 | for(int i = 0; i < temperatures.Length; i++) 23 | { 24 | temperatures[i] = (int)Math.Round((temperatures[i] - 32) / 1.8); 25 | } 26 | } 27 | 28 | return Task.FromResult>(temperatures); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/WeatherSettings.cs: -------------------------------------------------------------------------------- 1 | namespace ConsoleApp1 2 | { 3 | internal sealed class WeatherSettings 4 | { 5 | public string Unit { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /samples/ConsoleApp1/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Trace", 5 | "Fluxera.Extensions.Hosting.ApplicationHost": "Trace", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "Serilog": { 10 | "MinimumLevel": { 11 | "Default": "Verbose", 12 | "Fluxera.Extensions.Hosting.ApplicationHost": "Verbose", 13 | "Override": { 14 | "Microsoft": "Information", 15 | "System": "Warning", 16 | "Microsoft.Hosting.Lifetime": "Information" 17 | } 18 | } 19 | }, 20 | "Weather": { 21 | "Unit": "C" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | latest 5 | disable 6 | disable 7 | false 8 | false 9 | 10 | 11 | 12 | Fluxera Software Development GmbH 13 | Fluxera Software Foundation 14 | Copyright © 2014-2024 Fluxera Software Development GmbH. All rights reserved. 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/MauiApp1/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/MauiApp1/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace MauiApp1 2 | { 3 | public partial class App : Application 4 | { 5 | public App() 6 | { 7 | this.InitializeComponent(); 8 | 9 | this.MainPage = new AppShell(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/MauiApp1/AppShell.xaml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /samples/MauiApp1/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace MauiApp1 2 | { 3 | public partial class AppShell : Shell 4 | { 5 | public AppShell() 6 | { 7 | this.InitializeComponent(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /samples/MauiApp1/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 10 | 15 | 16 |