Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Microsoft.FeatureManagement.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "examples\Cons
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TargetingConsoleApp", "examples\TargetingConsoleApp\TargetingConsoleApp.csproj", "{6558C21E-CF20-4278-AA08-EB9D1DF29D66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomAssignmentConsoleApp", "examples\CustomAssignmentConsoleApp\CustomAssignmentConsoleApp.csproj", "{06C10E31-4C33-4567-85DB-00056A2BB511}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -49,6 +51,10 @@ Global
{6558C21E-CF20-4278-AA08-EB9D1DF29D66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6558C21E-CF20-4278-AA08-EB9D1DF29D66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6558C21E-CF20-4278-AA08-EB9D1DF29D66}.Release|Any CPU.Build.0 = Release|Any CPU
{06C10E31-4C33-4567-85DB-00056A2BB511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06C10E31-4C33-4567-85DB-00056A2BB511}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06C10E31-4C33-4567-85DB-00056A2BB511}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06C10E31-4C33-4567-85DB-00056A2BB511}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -58,6 +64,7 @@ Global
{FDBB27BA-C5BA-48A7-BA9B-63159943EA9F} = {8ED6FFEE-4037-49A2-9709-BC519C104A90}
{E50FB931-7A42-440E-AC47-B8DFE5E15394} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{6558C21E-CF20-4278-AA08-EB9D1DF29D66} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{06C10E31-4C33-4567-85DB-00056A2BB511} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {84DA6C54-F140-4518-A1B4-E4CF42117FBD}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>Consoto.Banking.AccountService</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.FeatureManagement\Microsoft.FeatureManagement.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
12 changes: 12 additions & 0 deletions examples/CustomAssignmentConsoleApp/DailyDiscountOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
namespace Consoto.Banking.HelpDesk
{
class DailyDiscountOptions
{
public string ProductName { get; set; }

public int Discount { get; set; }
}
}
49 changes: 49 additions & 0 deletions examples/CustomAssignmentConsoleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using Consoto.Banking.AccountService;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.FeatureManagement;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Consoto.Banking.HelpDesk
{
class Program
{
public static async Task Main(string[] args)
{
//
// Setup configuration
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.Build();

//
// Setup application services + feature management
IServiceCollection services = new ServiceCollection();

services.AddSingleton(typeof(IFeatureVariantAssignerMetadata), typeof(RecurringAssigner));

services.AddSingleton(configuration)
.AddFeatureManagement()
.AddFeatureVariantAssigner<RecurringAssigner>();

//
// Get the feature manager from application services
using (ServiceProvider serviceProvider = services.BuildServiceProvider())
{
IFeatureVariantManager variantManager = serviceProvider.GetRequiredService<IFeatureVariantManager>();

DailyDiscountOptions discountOptions = await variantManager
.GetVariantAsync<DailyDiscountOptions>("DailyDiscount", CancellationToken.None);

//
// Output results
Console.WriteLine($"Today there is a {discountOptions.Discount}% discount on {discountOptions.ProductName}!");
}
}
}
}
41 changes: 41 additions & 0 deletions examples/CustomAssignmentConsoleApp/RecurringAssigner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using Microsoft.Extensions.Configuration;
using Microsoft.FeatureManagement;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Consoto.Banking.AccountService
{
[AssignerAlias("Recurring")]
class RecurringAssigner : IFeatureVariantAssigner
{
public ValueTask<FeatureVariant> AssignVariantAsync(FeatureVariantAssignmentContext variantAssignmentContext, CancellationToken _)
{
FeatureDefinition featureDefinition = variantAssignmentContext.FeatureDefinition;

FeatureVariant chosenVariant = null;

string currentDay = DateTimeOffset.UtcNow.DayOfWeek.ToString();

foreach (var variant in featureDefinition.Variants)
{
RecurringAssignmentParameters p = variant.AssignmentParameters.Get<RecurringAssignmentParameters>() ??
new RecurringAssignmentParameters();

if (p.Days != null &&
p.Days.Any(d => d.Equals(currentDay, StringComparison.OrdinalIgnoreCase)))
{
chosenVariant = variant;

break;
}
}

return new ValueTask<FeatureVariant>(chosenVariant);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using System.Collections.Generic;

namespace Consoto.Banking.AccountService
{
class RecurringAssignmentParameters
{
public List<string> Days { get; set; }
}
}
33 changes: 33 additions & 0 deletions examples/CustomAssignmentConsoleApp/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"FeatureManagement": {
"DailyDiscount": {
"Assigner": "Recurring",
"Variants": [
{
"Default": true,
"Name": "Default",
"ConfigurationReference": "DailyDiscount:Default"
},
{
"Name": "Special",
"ConfigurationReference": "DailyDiscount:Special",
"AssignmentParameters": {
"Days": [
"Tuesday"
]
}
}
]
}
},
"DailyDiscount": {
"Default": {
"Discount": 20,
"ProductName": "Bananas"
},
"Special": {
"Discount": 30,
"ProductName": "Fish"
}
}
}
4 changes: 2 additions & 2 deletions examples/FeatureFlagDemo/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public async Task<IActionResult> About(CancellationToken cancellationToken)
{
ViewData["Message"] = "Your application description page.";

if (await _featureManager.IsEnabledAsync(nameof(MyFeatureFlags.CustomViewData), cancellationToken))
if (await _featureManager.IsEnabledAsync(MyFeatureFlags.CustomViewData, cancellationToken))
{
ViewData["Message"] = $"This is FANCY CONTENT you can see only if '{nameof(MyFeatureFlags.CustomViewData)}' is enabled.";
ViewData["Message"] = $"This is FANCY CONTENT you can see only if '{MyFeatureFlags.CustomViewData}' is enabled.";
};

return View();
Expand Down
14 changes: 14 additions & 0 deletions examples/FeatureFlagDemo/DiscountBannerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
namespace FeatureFlagDemo
{
public class DiscountBannerOptions
{
public int Size { get; set; }

public string Color { get; set; }

public string Background { get; set; }
}
}
14 changes: 6 additions & 8 deletions examples/FeatureFlagDemo/MyFeatureFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
//
namespace FeatureFlagDemo
{
//
// Define feature flags in an enum
public enum MyFeatureFlags
static class MyFeatureFlags
{
Home,
Beta,
CustomViewData,
ContentEnhancement,
EnhancedPipeline
public const string Home = "Home";
public const string Beta = "Beta";
public const string CustomViewData = "CustomViewData";
public const string ContentEnhancement = "ContentEnhancement";
public const string EnhancedPipeline = "EnhancedPipeline";
}
}
1 change: 1 addition & 0 deletions examples/FeatureFlagDemo/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public void ConfigureServices(IServiceCollection services)
.AddFeatureFilter<TimeWindowFilter>()
.AddFeatureFilter<PercentageFilter>()
.AddFeatureFilter<TargetingFilter>()
.AddFeatureVariantAssigner<TargetingFeatureVariantAssigner>()
.UseDisabledFeaturesHandler(new FeatureNotEnabledDisabledHandler());

services.AddMvc(o =>
Expand Down
20 changes: 18 additions & 2 deletions examples/FeatureFlagDemo/Views/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<!DOCTYPE html>
@using Microsoft.FeatureManagement
@inject IFeatureVariantManager variantManager;
@{
DiscountBannerOptions opts = await variantManager.GetVariantAsync<DiscountBannerOptions>("DiscountBanner", Context.RequestAborted);
}

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
Expand All @@ -15,6 +21,14 @@
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
<style type="text/css">
.notification-banner {
text-align: center;
color: @opts.Color;
font-size: @(opts.Size)px;
background: @(opts.Background)
}
</style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
Expand Down Expand Up @@ -42,7 +56,9 @@
</nav>

<partial name="_CookieConsentPartial" />

<div class="notification-banner">
New Sale, 50% Off !
</div>
<div class="container body-content">
@RenderBody()
</div>
Expand Down
45 changes: 45 additions & 0 deletions examples/FeatureFlagDemo/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,51 @@
}
}
]
},
"DiscountBanner": {
"Assigner": "Targeting",
"Variants": [
{
"Default": true,
"Name": "Big",
"ConfigurationReference": "DiscountBanner:Big"
},
{
"Name": "Small",
"ConfigurationReference": "DiscountBanner:Small",
"AssignmentParameters": {
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 80
},
{
"Name": "Ring1",
"RolloutPercentage": 50
}
],
"DefaultRolloutPercentage": 20
}
}
}
]
}
},
"DiscountBanner": {
"Small": {
"Size": 24,
"Color": "#c9f568",
"Background": "#f35220"
},
"Big": {
"Size": 48,
"Color": "#007cb3",
"Background": "#ffbb02"
}
}
}
12 changes: 12 additions & 0 deletions examples/TargetingConsoleApp/CartOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
namespace Consoto.Banking.HelpDesk
{
class CartOptions
{
public int Size { get; set; }

public string Color { get; set; }
}
}
Loading