### Install Esquio.AspNetCore package Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Installs the Esquio.AspNetCore package via .NET CLI. ```bash dotnet add package Esquio.AspNetCore ``` -------------------------------- ### Install Microsoft.ApplicationInsights.AspNetCore via Package Manager Source: https://esquio.readthedocs.io/en/latest/started/diagnostics.html Use PowerShell or Package Manager to install the Microsoft.ApplicationInsights.AspNetCore package. ```powershell Install-Package Microsoft.ApplicationInsights.AspNetCore ``` -------------------------------- ### Install Esquio.CLI Source: https://esquio.readthedocs.io/en/latest/tools/esquiocli.html Command to install the Esquio.CLI tool globally using the .NET Core CLI. ```bash dotnet tool install -g Esquio.Cli ``` -------------------------------- ### Install Esquio packages via CLI Source: https://esquio.readthedocs.io/en/latest/started/worker.html Install the core Esquio package and the configuration store provider. ```bash dotnet add package Esquio dotnet add package Esquio.Configuration.Store dotnet restore ``` -------------------------------- ### Install Esquio.Configuration.Store via .NET Core CLI Source: https://esquio.readthedocs.io/en/latest/stores/configuration.html Command to add the Esquio.Configuration.Store package using the .NET Core CLI. ```bash dotnet add package Esquio.Configuration.Store ``` -------------------------------- ### Install Esquio.Configuration.Store via Package Manager Source: https://esquio.readthedocs.io/en/latest/stores/configuration.html Command to install the Esquio.Configuration.Store package using PowerShell or Package Manager. ```powershell Install-Package Esquio.Configuration.Store ``` -------------------------------- ### Run the application with dotnet run Source: https://esquio.readthedocs.io/en/latest/started/worker.html Execute this command in your terminal to start the application on your local machine. ```bash dotnet run ``` -------------------------------- ### Install Microsoft.ApplicationInsights.AspNetCore via .NET Core CLI Source: https://esquio.readthedocs.io/en/latest/started/diagnostics.html Use the .NET Core CLI to add the Microsoft.ApplicationInsights.AspNetCore package to your project. ```bash dotnet add package Microsoft.ApplicationInsights.AspNetCore ``` -------------------------------- ### Install MiniProfiler.Esquio via .NET Core CLI Source: https://esquio.readthedocs.io/en/latest/tools/miniprofiler.html Command to install the MiniProfiler.Esquio package using the .NET Core CLI. ```bash dotnet package add MiniProfiler.Esquio ``` -------------------------------- ### Install Esquio packages via PowerShell Source: https://esquio.readthedocs.io/en/latest/started/worker.html Alternative installation method using PowerShell or Package Manager. ```powershell Install-Package Esquio Install-Package Esquio.Configuration.Store ``` -------------------------------- ### Install Esquio.AspNetCore via Package Manager Source: https://esquio.readthedocs.io/en/latest/tools/miniprofiler.html Command to install the Esquio.AspNetCore package using PowerShell or the Package Manager console. ```powershell Install-Package Esquio.AspNetCore ``` -------------------------------- ### Install Esquio packages via PowerShell/Package Manager Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Alternative installation commands using PowerShell or Package Manager. ```powershell Install-Package Microsoft.Extensions.DependencyInjection Install-Package Microsoft.Extensions.Logging.Console Install-Package Microsoft.Extensions.Configuration.Json Install-Package Esquio.Configuration.Store ``` -------------------------------- ### Install Esquio.Http.Store via .NET Core CLI Source: https://esquio.readthedocs.io/en/latest/stores/http.html Command to add the Esquio Http store package to your project using the .NET Core CLI. ```bash dotnet add package Esquio.Http.Store ``` -------------------------------- ### Install Esquio packages via .NET CLI Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Adds required NuGet packages for Esquio, logging, and configuration, then restores dependencies. ```bash dotnet package add Microsoft.Extensions.DependencyInjection dotnet package add Microsoft.Extensions.Logging.Console dotnet package add Microsoft.Extensions.Configuration.Json dotnet package add Esquio.Configuration.Store dotnet restore ``` -------------------------------- ### Docker Compose commands for local deployment with different databases Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html Run these commands from the build directory to start Esquio UI locally with SQL Server, PostgreSQL, or MySQL. Each command uses a specific docker-compose file. ```bash docker-compose -f ./build/docker-compose-demo-with-ui-sqlserver up --build docker-compose -f ./build/docker-compose-demo-with-ui-npgsql up --build docker-compose -f ./build/docker-compose-demo-with-ui-mysql up --build ``` -------------------------------- ### YAML pipeline example for set-toggle-parameter@1 task Source: https://esquio.readthedocs.io/en/latest/started/azuredevopstasks.html YAML configuration for the Esquio 'Set toggle parameter' task. It sets the parameter 'Percentage' to value '59' for toggle ID 14. The IDs in the example are placeholders and will differ in real usage. ```yaml - task: set-toggle-parameter@1 inputs: EsquioService: 'esquio' productId: '1' flagId: '2' toggleId: '14' parameterId: 'Percentage' parameterValue: '59' ``` -------------------------------- ### Obtain IFeatureService Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Gets the IFeatureService from the service provider. ```csharp var featureService = serviceProvider.GetService(); ``` -------------------------------- ### Configure GradualRolloutSessionToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Example configuration for a toggle that enables a feature based on the percentage of ASP.NET Core session identifiers. ```json { "Name": "DarkMode", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.GradualRolloutSessionToggle", "Parameters": { "Percentage": 50 } } ] } ``` -------------------------------- ### Configure GradualRolloutHeaderValueToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Example configuration for a toggle that enables a feature based on the percentage of users identified by a specific HTTP header value. ```json { "Name": "DarkMode", "Enabled": true, "Toggles": [ { "Type": "Esquio.Toggles.GradualRolloutHeaderValueToggle", "Parameters": { "Percentage": 50, "HeaderName": "X-Tenant" } } ] } ``` -------------------------------- ### Register custom toggle in Startup with RegisterTogglesFromAssemblyContaining Source: https://esquio.readthedocs.io/en/latest/toggles/extensibility.html Registers the custom toggle by calling RegisterTogglesFromAssemblyContaining() on the Esquio setup in the Startup class. ```csharp services.AddEsquio(setup => setup.RegisterTogglesFromAssemblyContaining()) ``` -------------------------------- ### Install Esquio.Http.Store via Package Manager Source: https://esquio.readthedocs.io/en/latest/stores/http.html Command to add the Esquio Http store package to your project using PowerShell or the Package Manager console. ```powershell Install-Package Esquio.Http.Store ``` -------------------------------- ### Query Feature State Disabled Output Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Example JSON response showing a feature as disabled. ```json [ { "enabled": false, "name": "Colored" } ] ``` -------------------------------- ### Query Feature State JSON Output Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Example JSON response when querying the Esquio endpoint for feature status. ```json [ { "enabled": true, "name": "Colored" } ] ``` -------------------------------- ### FromToToggle configuration example Source: https://esquio.readthedocs.io/en/latest/toggles/esquio.html Configures the FromToToggle to enable the feature when the current UTC date falls between 2019-06-12 00:00:00 and 2019-06-14 23:59:59. The toggle type is Esquio.Toggles.FromToToggle with parameters From and To in yyyy-MM-dd HH:mm:ss format. ```json { "Name": "DarkMode", "Enabled": true, "Toggles": [ { "Type": "Esquio.Toggles.FromToToggle", "Parameters": { "From": "2019-06-12 00:00:00", "To": "2019-06-14 23:59:59" } } ] } ``` -------------------------------- ### Complete IsActiveAsync method and GetCurrentBrowser helper Source: https://esquio.readthedocs.io/en/latest/toggles/extensibility.html Full implementation of IsActiveAsync that retrieves the feature, gets the toggle data, checks the current browser against allowed browsers, and logs results. Includes a private GetCurrentBrowser helper that reads the User-Agent header. ```csharp public async Task IsActiveAsync( string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(typeof(UserAgentBrowserToggle).FullName); var data = toggle.GetData(); var allowedBrowsers = data.Browsers.ToString(); var currentBrowser = GetCurrentBrowser(); if (allowedBrowsers != null && !String.IsNullOrEmpty(currentBrowser)) { _logger.LogDebug("{nameof(UserAgentBrowserToggle)} is trying to verify if {currentBrowser} is satisfying allowed browser configuration."); var tokenizer = new StringTokenizer(allowedBrowsers, split_characters); foreach (var segment in tokenizer) { if (segment.Value?.IndexOf(currentBrowser, StringComparison.InvariantCultureIgnoreCase) >= 0) { _logger.LogInformation("The browser {currentBrowser} is satisfied using {allowedBrowsers} configuration."); return true; } } } _logger.LogInformation("The browser {currentBrowser} is not allowed using current toggle configuration."); return false; } private string GetCurrentBrowser() { return _contextAccessor.HttpContext .Request .Headers[UserAgent] .FirstOrDefault() ?? string.Empty; } ``` -------------------------------- ### EnvironmentToggle configuration example Source: https://esquio.readthedocs.io/en/latest/toggles/esquio.html Configures the EnvironmentToggle to enable the feature when the ASPNETCORE_ENVIRONMENT variable is set to Staging or Production. The toggle type is Esquio.Toggles.EnvironmentToggle and parameters include EnvironmentVariable and Values separated by ';'. ```json { "Name": "MinutesRealTime", "Enabled": true, "Toggles": [ { "Type": "Esquio.Toggles.EnvironmentToggle", "Parameters": { "EnvironmentVariable": "ASPNETCORE_ENVIRONMENT", "Values": "Staging;Production" } } ] } ``` -------------------------------- ### Configure NotFoundBehavior with AddEsquio Source: https://esquio.readthedocs.io/en/latest/options/behaviors.html Sets the behavior when a feature does not exist in the store. In this example, NotFoundBehavior.SetDisabled is configured, so Esquio returns disabled as the result of the feature evaluation if the feature is not found. ```csharp services .AddEsquio(setup => setup.ConfigureNotFoundBehavior(NotFoundBehavior.SetDisabled)) .AddAspNetCoreDefaultServices() .AddConfigurationStore(Configuration, "Esquio"); ``` -------------------------------- ### Create new ASP.NET Core project Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Initializes a new empty ASP.NET Core web project using the .NET CLI. ```bash dotnet new web -n GettingStarted.AspNetCore.Intro ``` -------------------------------- ### Register ConfigurationStore in Startup.cs Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Configures the Startup class to use the configuration store for feature management. ```csharp public class Startup { IConfiguration _configuration; public Startup(IConfiguration configuration) { _configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services .AddEsquio() .AddAspNetCoreDefaultServices() .AddConfigurationStore(_configuration); } ``` -------------------------------- ### Configure custom root for ConfigurationStore Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Demonstrates how to specify a custom root key when adding the configuration store. ```csharp .AddConfigurationStore(_configuration, key: "MyNewCustomRoot"); ``` -------------------------------- ### Register Esquio configuration store in Startup Source: https://esquio.readthedocs.io/en/latest/stores/configuration.html C# code to register the configuration store in the Startup class using AddConfigurationStore. ```csharp public class Startup { IConfiguration _configuration; public Startup(IConfiguration configuration) { _configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services .AddEsquio() .AddConfigurationStore(_configuration); } ``` -------------------------------- ### Register Http Store in Startup Source: https://esquio.readthedocs.io/en/latest/stores/http.html Configuration for the Http store within the ConfigureServices method of the Startup class, specifying the base address and API key. ```csharp AddEsquio() .AddHttpStore(options => { options .UseBaseAddress("http://localhost:1368/") //this is Esquio UI base address .UseApiKey("b6+KYpSY8VPMBmHLNJ00z80aPOe+Li4EGe4idoKKI1A="); // this is a Api Key on Esquio UI (only Reader permission is Required) }); ``` -------------------------------- ### Create project folder Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Commands to create and enter a new directory for the console application. ```bash mkdir consoleapp cd consoleapp ``` -------------------------------- ### Create the worker project Source: https://esquio.readthedocs.io/en/latest/started/worker.html Use the .NET Core CLI to scaffold a new worker project. ```bash dotnet new worker -n GettingStarted.Worker cd GettingStarted.Worker ``` -------------------------------- ### Create .NET Core console project Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Uses the .NET Core CLI to create a new console project. ```bash dotnet new console ``` -------------------------------- ### Register Esquio services and configuration store Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Sets up ServiceCollection with logging, Esquio, and the configuration store. ```csharp var services = new ServiceCollection() .AddLogging(configure => configure.AddConsole()) .AddEsquio() .AddConfigurationStore(configuration, "Esquio") .Services; ``` -------------------------------- ### Write welcome message Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Outputs a message and waits for a key press. ```csharp Console.WriteLine("Welcome to Esquio!"); Console.Read(); ``` -------------------------------- ### Import configuration namespace Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Adds the using directive for Microsoft.Extensions.Configuration. ```csharp using Microsoft.Extensions.Configuration; ``` -------------------------------- ### Configure OnErrorBehavior with AddEsquio Source: https://esquio.readthedocs.io/en/latest/options/behaviors.html Sets the behavior when a feature fails during evaluation. In this example, OnErrorBehavior.Throw is configured, so the exception will be thrown if a failure occurs during evaluation. ```csharp services .AddEsquio(setup => setup.ConfigureOnErrorBehavior(OnErrorBehavior.Throw)) .AddAspNetCoreDefaultServices() .AddConfigurationStore(Configuration, "Esquio"); ``` -------------------------------- ### Enable Scoped Evaluation Source: https://esquio.readthedocs.io/en/latest/options/scopedevaluation.html Use the UseScopedEvaluation method within the AddEsquio setup to cache evaluation results in the HTTP Context Items property. ```csharp services.AddEsquio(setup=> { setup.UseScopedEvaluation(useScopedEvaluation: true); }); ``` -------------------------------- ### Run the application Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Runs the console app using dotnet run. ```bash dotnet run ``` -------------------------------- ### Display Esquio CLI Help Source: https://esquio.readthedocs.io/en/latest/tools/esquiocli.html Displays the usage information and available options for the dotnet-esquio command. ```bash Usage: dotnet-esquio [options] [command] Options: -?|-h|--help Show help information ``` -------------------------------- ### Configure Esquio with Application Insights in Startup.ConfigureServices Source: https://esquio.readthedocs.io/en/latest/started/diagnostics.html Modify the ConfigureServices method to add Esquio with scoped evaluation, default ASP.NET Core services, Application Insights processor, and configuration store. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews() .Services .AddEsquio(setup => { setup.UseScopedEvaluation(useScopedEvaluation: true); }) .AddAspNetCoreDefaultServices() .AddApplicationInsightProcessor() .AddConfigurationStore(Configuration); } ``` -------------------------------- ### Add appsettings.json with Esquio configuration Source: https://esquio.readthedocs.io/en/latest/started/netcore.html JSON configuration defining a product 'Console' with a feature 'Colored' enabled. ```json { "Esquio": { "Products": [ { "Name": "Console", "Features": [ { "Name": "Colored", "Enabled": true, "Toggles": [] } ] } ] } } ``` -------------------------------- ### Create configuration object Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Builds an IConfiguration from appsettings.json using ConfigurationBuilder. ```csharp var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); ``` -------------------------------- ### Register Esquio services in Startup.cs Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Registers the default Esquio and ASP.NET Core services within the ConfigureServices method. ```csharp services .AddEsquio() .AddAspNetCoreDefaultServices(); ``` -------------------------------- ### Build service provider Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Builds the service provider from the configured services. ```csharp var serviceProvider = services.BuildServiceProvider(); ``` -------------------------------- ### Import Esquio.Abstractions namespace Source: https://esquio.readthedocs.io/en/latest/started/worker.html Add the required namespace for resolving IFeatureService. ```csharp using Esquio.Abstractions; ``` -------------------------------- ### Enable features in appsettings.json Source: https://esquio.readthedocs.io/en/latest/started/worker.html Update the configuration file to enable the desired feature. ```json "Enabled": true ``` -------------------------------- ### Configure Http Store with Cache Source: https://esquio.readthedocs.io/en/latest/stores/http.html Configuration for the Http store including the optional cache enabled via the UseCache extension method. ```csharp AddEsquio() .AddHttpStore(options => { options .UseBaseAddress("http://localhost:1368/") //this is Esquio UI base address .UseApiKey("b6+KYpSY8VPMBmHLNJ00z80aPOe+Li4EGe4idoKKI1A=") // this is a Api Key on Esquio UI (only Reader permission is Required) .UseCache(true, slidingExpiration: TimeSpan.FromSeconds(10)); }); ``` -------------------------------- ### Apply Kubernetes configuration Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html Applies the configuration defined in esquio-ui.yaml to the cluster. ```bash kubectl apply -f esquio-ui.yaml ``` -------------------------------- ### Register Esquio in Program.cs Source: https://esquio.readthedocs.io/en/latest/started/worker.html Register Esquio services and the configuration store within the CreateHostBuilder method. ```csharp public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((context, services) => { services .AddEsquio() .AddConfigurationStore(context.Configuration, key: "Esquio"); services.AddHostedService(); }); ``` -------------------------------- ### Save connection string to file Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html Saves your connection string into a local file named connection-string.txt. ```bash echo '' > ./connection-string.txt ``` -------------------------------- ### Run Esquio UI Docker container with environment variables Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html Run the Esquio UI Docker image with required environment variables for database and OpenID configuration. Replace placeholders with your actual values. The Data__Store variable accepts SqlServer, MySql, or NpgSql. Security__OpenId__IsAzure must be true when using Azure AD. ```bash docker run xabarilcoding/esquioui:4.0.0 -p 9000:80 \ -e Data__ConnectionString= \ -e Data__Store=[SqlServer|MySql|NpgSql] -e Security__DefaultUsers__0__ApplicationRole=[Contributor|Reader|Management] -e Security__DefaultUsers__0__SubjectId= -e Security__OpenId__ClientId= \ -e Security__OpenId__Audience= \ -e Security__OpenId__Scope= \ -e Security__OpenId__Authority= \ -e Security__OpenId__ResponseType= \ -e Security__OpenId__IsAzure= ``` -------------------------------- ### Define features in appsettings.json Source: https://esquio.readthedocs.io/en/latest/started/worker.html Add the Esquio configuration section to your appsettings.json file. ```json "Esquio": { "Products": [ { "Name": "default", "Features": [ { "Name": "ComputeMatch", "Enabled": false, "Toggles": [] } ] } ] } ``` -------------------------------- ### Define Kubernetes deployment and service Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html YAML configuration for the Esquio UI service and deployment, saved as esquio-ui.yaml. ```yaml apiVersion: v1 kind: Service metadata: name: esquio-ui-release labels: app.kubernetes.io/name: esquio-ui app.kubernetes.io/instance: esquio-ui-release spec: type: LoadBalancer ports: - port: 80 targetPort: http protocol: TCP name: http selector: app.kubernetes.io/name: esquio-ui app.kubernetes.io/instance: esquio-ui-release --- apiVersion: apps/v1beta2 kind: Deployment metadata: name: esquio-ui-release labels: app.kubernetes.io/name: esquio-ui app.kubernetes.io/instance: esquio-ui-release spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: esquio-ui app.kubernetes.io/instance: esquio-ui-release template: metadata: labels: app.kubernetes.io/name: esquio-ui app.kubernetes.io/instance: esquio-ui-release spec: containers: - name: esquio-ui image: "xabarilcoding/esquioui:3.0.0" imagePullPolicy: IfNotPresent env: - name: ASPNETCORE_ENVIRONMENT value: "Development" - name: DATA__CONNECTIONSTRING valueFrom: secretKeyRef: name: esquio-ui-secret key: connection-string - name: DATA__STORE value: "[SqlServer|NpgSql|MySql]" - name: SECURITY__DEFAULTUSERS__0__APPLICATIONROLE value: "[Contributor|Reader]" - name: SECURITY__DEFAULTUSERS__0__SUBJECTID value: "" - name: DATA__STORE value: "[SqlServer|NpgSql|MySql]" - name: SECURITY__OPENID__CLIENTID value: "" - name: SECURITY__OPENID__AUDIENCE value: "" - name: SECURITY__OPENID__SCOPE value: "" - name: SECURITY__OPENID__AUTHORITY value: "" - name: SECURITY__OPENID__RESPONSETYPE value: "" - name: Security__OpenId__IsAzure value: "" ports: - name: http containerPort: 80 protocol: TCP ``` -------------------------------- ### Configure HostNameToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Enables a feature if the client instance hostname matches one of the provided values. ```json { "Name": "MinutesProgressBar", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.HostNameToggle", "Parameters": { "HostNames": "mycompany.org;en.domain.com" } } ] } ``` -------------------------------- ### Configure ServerIpAddressToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Enables a feature if the host IP address matches one of the provided addresses in the IpAddresses parameter. ```json { "Name": "MinutesProgressBar", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.ServerIpAddressToggle", "Parameters": { "IpAddresses": "11.22.44.88;11.22.33.44" } } ] } ``` -------------------------------- ### MapEsquio endpoint in Startup.Configure Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Adds the Esquio endpoint with MapEsquio() and requires the 'HiddenGem' feature for the root endpoint. The default URI pattern is 'esquio', so you can query /esquio?featureName=HiddenGem. ```csharp app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); }).RequireFeature("HiddenGem"); endpoints.MapEsquio(); }); ``` -------------------------------- ### Configure Esquio in appsettings.json Source: https://esquio.readthedocs.io/en/latest/stores/configuration.html JSON configuration for Esquio with a product and feature named HiddenGem. ```json { "Esquio": { "Products": [ { "Name": "default", "Features": [ { "Name": "HiddenGem", "Enabled": true, "Toggles": [] } ] } ] } } ``` -------------------------------- ### Inject services into UserAgentBrowserToggle constructor Source: https://esquio.readthedocs.io/en/latest/toggles/extensibility.html Constructor that injects IRuntimeFeatureStore, IHttpContextAccessor, and ILogger services, with null checks throwing ArgumentNullException. ```csharp public UserAgentBrowserToggle( IRuntimeFeatureStore featureStore, IHttpContextAccessor httpContextAccessor, ILogger logger) { _featureStore = featureStore ?? throw new ArgumentNullException(nameof(featureStore)); _contextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } ``` -------------------------------- ### ConfigureDefaultProductName Source: https://esquio.readthedocs.io/en/latest/options/defaults.html Configures the default Product name, which defaults to 'default'. ```csharp services.AddEsquio(setup=> { setup.ConfigureDefaultProductName("default"); }); ``` -------------------------------- ### ClientIpAddressToggle configuration Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Configuration for the ClientIpAddressToggle. The feature is enabled if the client IP address is in the list '11.22.44.88;11.22.33.44'. Note the parameters use 'ClaimType' and 'ClaimValues' keys, though the documented parameter is 'IpAddresses'. ```json { "Name": "SecretZoneMatch", "Enabled": true, "Toggles": [ { "Type": "Esquio.Toggles.ClientIpAddressToggle", "Parameters": { "ClaimType": "IpAddresses", "ClaimValues": "11.22.44.88;11.22.33.44" } } ] } ``` -------------------------------- ### Import DependencyInjection namespace Source: https://esquio.readthedocs.io/en/latest/started/worker.html Add the required namespace for dependency injection extensions. ```csharp using Microsoft.Extensions.DependencyInjection; ``` -------------------------------- ### Configure GradualRolloutUserNameToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Configures a toggle that enables a feature for a percentage of users based on their username. Stickiness is maintained via Jenkins hash. ```json { "Name": "DarkMode", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.GradualRolloutUserNameToggle", "Parameters": { "Percentage": 50 } } ] } ``` -------------------------------- ### Configure MiniProfiler with Esquio in ASP.NET Core Source: https://esquio.readthedocs.io/en/latest/tools/miniprofiler.html Configuration code to register MiniProfiler services and the Esquio plugin in the ASP.NET Core dependency injection container. ```csharp services .AddMiniProfiler(options => { options.RouteBasePath = "/profiler"; options.EnableServerTimingHeader = true; options.ResultsAuthorize = (_) => true; options.ShouldProfile = _ => true; options.IgnoredPaths.Add("/lib"); options.IgnoredPaths.Add("/css"); options.IgnoredPaths.Add("/js"); options.IgnoredPaths.Add("/assets"); }).AddEsquio(); ``` -------------------------------- ### Configure HostEnvironmentToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Configures a toggle that enables a feature based on the current ASP.NET Core host environment. ```json { "Name": "MinutesProgressBar", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.HostEnvironmentToggle", "Parameters": { "Environments": "Staging;Production" } } ] } ``` -------------------------------- ### ConfigureDefaultProductName Source: https://esquio.readthedocs.io/en/latest/options/defaults.html Configures the default Product name to use. The default value is 'default'. ```APIDOC ## ConfigureDefaultProductName ### Description Configures the default Product name to use. The default value is 'default'. ### Method ConfigureDefaultProductName ### Parameters - **productName** (string) - Required - The default Product name to use. ### Request Example ```csharp services.AddEsquio(setup=> { setup.ConfigureDefaultProductName("default"); }); ``` ``` -------------------------------- ### Execute logic with Do method Source: https://esquio.readthedocs.io/en/latest/started/worker.html Use the Do method to define separate actions for enabled and disabled feature states. ```csharp protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using (var scope = _scopeFactory.CreateScope()) { var featureService = scope.ServiceProvider .GetRequiredService(); await featureService.Do("ComputeMatch", enabled: () => { _logger.LogInformation("Worker running with ComputeMatch Feature enabled at: {time}", DateTimeOffset.Now); }, disabled: () => { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); }); await Task.Delay(1000, stoppingToken); } } } ``` -------------------------------- ### Expose Esquio Endpoint for SPA Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Insert the middleware in the Configure method to expose an endpoint for querying feature states. ```csharp app.UseEndpoints(routes => { routes.MapEsquio(pattern: "esquio"); }); ``` -------------------------------- ### Change Main method to async Source: https://esquio.readthedocs.io/en/latest/started/netcore.html Modify the Program.cs Main method to be async to support await calls. ```csharp static async Task Main(string[] args) ``` -------------------------------- ### Implement IToggle interface with IsActiveAsync method Source: https://esquio.readthedocs.io/en/latest/toggles/extensibility.html Initial implementation of a custom toggle that implements the IToggle interface. The IsActiveAsync method is left empty and must be completed to return a boolean indicating whether the feature is active. ```csharp public class UserAgentBrowserToggle : IToggle { public async Task IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { } } ``` -------------------------------- ### Register TagHelper in _ViewImports.cshtml Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Add the Esquio tag helper to your _ViewImports.cshtml file to enable it in your views. ```cshtml ... @using Esquio @using Esquio.Abstractions @using Esquio.AspNetCore ... @addTagHelper *, Esquio.AspNetCore ``` -------------------------------- ### Esquio rollout feature task YAML Source: https://esquio.readthedocs.io/en/latest/started/azuredevopstasks.html YAML configuration for the esquio-rollout-feature@1 task. Requires an Esquio Service Endpoint, product ID, and flag ID. The task enables a feature for everyone by cleaning all toggles. ```yaml - task: esquio-rollout-feature@1 inputs: EsquioService: 'Esquio' productId: '1' flagId: '1' ``` -------------------------------- ### Create Kubernetes secret Source: https://esquio.readthedocs.io/en/latest/ui/deployment.html Creates a generic Kubernetes secret named esquio-ui-secret using the connection string file. ```bash kubectl create secret generic esquio-ui-secret --from-file=connection-string=./connection-string.txt ``` -------------------------------- ### Initialize IFeatureService scope Source: https://esquio.readthedocs.io/en/latest/started/worker.html Create a service scope within ExecuteAsync to resolve IFeatureService. ```csharp protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using (var scope = _scopeFactory.CreateScope()) { var featureService = scope.ServiceProvider .GetRequiredService(); } ``` -------------------------------- ### Configure UserAgentToggle Source: https://esquio.readthedocs.io/en/latest/toggles/aspnetcore.html Enables a feature if the request user agent matches one of the browsers specified in the Browsers parameter. ```json { "Name": "MinutesProgressBar", "Enabled": true, "Toggles": [ { "Type": "Esquio.AspNetCore.Toggles.UserAgentToggle", "Parameters": { "Browsers": "Mozilla/5.0;Chrome/81.0.4" } } ] } ``` -------------------------------- ### Add fallback redirect to Google Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Uses the built-in EndpointFallbackAction.RedirectTo to redirect to https://www.google.com when the feature is disabled. This replaces the custom request delegate. ```csharp .AddEsquio(options => { options.ConfigureNotFoundBehavior(NotFoundBehavior.SetDisabled); options.ConfigureOnErrorBehavior(OnErrorBehavior.SetDisabled); }) .AddEndpointFallback(EndpointFallbackAction.RedirectTo("https://www.google.com")) ``` -------------------------------- ### Configure Endpoint Fallback Source: https://esquio.readthedocs.io/en/latest/started/aspnetcore.html Use AddEndpointFallback to define custom behavior when no matching endpoints are found. ```csharp services .AddEsquio() .AddAspNetCoreDefaultServices() .AddConfigurationStore(Configuration, "Esquio") .AddEndpointFallback((context) => { context.Response.StatusCode = StatusCodes.Status404NotFound; return Task.CompletedTask; }) ```