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
30 changes: 5 additions & 25 deletions Microsoft.FeatureManagement.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{FB
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.FeatureManagement.AspNetCore", "tests\Tests.FeatureManagement.AspNetCore\Tests.FeatureManagement.AspNetCore.csproj", "{FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "examples\ConsoleApp\ConsoleApp.csproj", "{7B98D293-F270-423E-A9A6-0D388E903AE9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "examples\ConsoleApp\ConsoleApp.csproj", "{7B98D293-F270-423E-A9A6-0D388E903AE9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPages", "examples\RazorPages\RazorPages.csproj", "{36DBB413-D9CA-4C56-AE5B-EAEA4C344DB3}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorPages", "examples\RazorPages\RazorPages.csproj", "{36DBB413-D9CA-4C56-AE5B-EAEA4C344DB3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FeatureFlagDemo", "examples\FeatureFlagDemo\FeatureFlagDemo.csproj", "{DACAB624-4611-42E8-844C-529F93A54980}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeatureFlagDemo", "examples\FeatureFlagDemo\FeatureFlagDemo.csproj", "{DACAB624-4611-42E8-844C-529F93A54980}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TargetingConsoleApp", "examples\TargetingConsoleApp\TargetingConsoleApp.csproj", "{283D3EBB-4716-4F1D-BA51-A435F7E2AB82}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TargetingConsoleApp", "examples\TargetingConsoleApp\TargetingConsoleApp.csproj", "{283D3EBB-4716-4F1D-BA51-A435F7E2AB82}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.FeatureManagement.Telemetry.ApplicationInsights", "src\Microsoft.FeatureManagement.Telemetry.ApplicationInsights\Microsoft.FeatureManagement.Telemetry.ApplicationInsights.csproj", "{7964DC66-B2D3-412D-B18A-86D1E07D149D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VariantAndTelemetryDemo", "examples\VariantAndTelemetryDemo\VariantAndTelemetryDemo.csproj", "{1502529E-47E9-4306-98C4-BF6CF7C7C275}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorServerApp", "examples\BlazorServerApp\BlazorServerApp.csproj", "{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VariantServiceDemo", "examples\VariantServiceDemo\VariantServiceDemo.csproj", "{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorServerApp", "examples\BlazorServerApp\BlazorServerApp.csproj", "{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -69,22 +63,10 @@ Global
{283D3EBB-4716-4F1D-BA51-A435F7E2AB82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{283D3EBB-4716-4F1D-BA51-A435F7E2AB82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{283D3EBB-4716-4F1D-BA51-A435F7E2AB82}.Release|Any CPU.Build.0 = Release|Any CPU
{7964DC66-B2D3-412D-B18A-86D1E07D149D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7964DC66-B2D3-412D-B18A-86D1E07D149D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7964DC66-B2D3-412D-B18A-86D1E07D149D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7964DC66-B2D3-412D-B18A-86D1E07D149D}.Release|Any CPU.Build.0 = Release|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1502529E-47E9-4306-98C4-BF6CF7C7C275}.Release|Any CPU.Build.0 = Release|Any CPU
{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E}.Release|Any CPU.Build.0 = Release|Any CPU
{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -96,9 +78,7 @@ Global
{36DBB413-D9CA-4C56-AE5B-EAEA4C344DB3} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{DACAB624-4611-42E8-844C-529F93A54980} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{283D3EBB-4716-4F1D-BA51-A435F7E2AB82} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{1502529E-47E9-4306-98C4-BF6CF7C7C275} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{12BAB5A6-4EEB-4917-B5D9-4AFB6253008E} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
{E8E17CB9-434E-4386-BF96-FA53BBFDCD6F} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {84DA6C54-F140-4518-A1B4-E4CF42117FBD}
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ Feature management provides a way to develop and expose application functionalit
* [ASP.NET Core Web App (Razor Page)](./examples/RazorPages)
* [ASP.NET Core Web App (MVC)](./examples/FeatureFlagDemo)
* [Blazor Server App](./examples/BlazorServerApp)
* [ASP.NET Core Web App with Variants and Telemetry](./examples/VariantAndTelemetryDemo)
* [ASP.NET Core Web App with Variant Service](./examples/VariantServiceDemo)

## Contributing

Expand Down
4 changes: 2 additions & 2 deletions examples/BlazorServerApp/BlazorServerApp.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.FeatureManagement\Microsoft.FeatureManagement.csproj" />
</ItemGroup>
Expand Down
53 changes: 21 additions & 32 deletions examples/BlazorServerApp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,34 @@ This app demonstrates how to use the Feature Management library in Blazor apps.
This app uses two feature flags: "BrowserEnhancement" and "Beta".

``` json
"feature_management": {
"feature_flags": [
{
"id": "BrowserEnhancement",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Browser",
"parameters": {
"AllowedBrowsers": [ "Edge" ]
"FeatureManagement": {
"BrowserEnhancement": {
"EnabledFor": [
{
"Name": "Browser",
"Parameters": {
"AllowedBrowsers": [ "Edge" ]
}
}
}
]
}
},
{
"id": "Beta",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Targeting",
"parameters": {
"Audience": {
"DefaultRolloutPercentage": 50,
"Exclusion": {
"Groups": [
"Guests"
]
"Beta": {
"EnabledFor": [
{
"Name": "Targeting",
"Parameters": {
"Audience": {
"DefaultRolloutPercentage": 50,
"Exclusion": {
"Groups": [
"Guests"
]
}
}
}
}
}
}
]
}
}
]
}
```

Expand All @@ -75,7 +65,6 @@ This app uses [cookie authentication](https://learn.microsoft.com/en-us/aspnet/c
Rather than `HttpContext`, the [`AuthenticationStateProvider`](https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-8.0#authenticationstateprovider-service) service is used to obtain the user authentication state information for setting targeting context. The details can be found in the [`MyTargetingContextAccessor`](./MyTargetingContextAccessor.cs).

## Service Registration

Blazor applications like this one typically pull ambient contextual data from scoped services. For example, the `UserAgentContext`, `AuthenticationStateProvider` and `ITargetingContextAccessor` are all scoped services. This pattern *breaks* if the feature management services are added as singleton, which is typical in non-blazor web apps.

In Blazor, *avoid* the following
Expand Down
58 changes: 24 additions & 34 deletions examples/BlazorServerApp/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,33 @@
}
},
"AllowedHosts": "*",
"feature_management": {
"feature_flags": [
{
"id": "BrowserEnhancement",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Browser",
"parameters": {
"AllowedBrowsers": [ "Edge" ]
}
}
]
"FeatureManagement": {
"BrowserEnhancement": {
"EnabledFor": [
{
"Name": "Browser",
"Parameters": {
"AllowedBrowsers": [ "Edge" ]
}
}
},
{
"id": "Beta",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Targeting",
"parameters": {
"Audience": {
"DefaultRolloutPercentage": 50,
"Exclusion": {
"Groups": [
"Guests"
]
}
}
]
},
"Beta": {
"EnabledFor": [
{
"Name": "Targeting",
"Parameters": {
"Audience": {
"DefaultRolloutPercentage": 50,
"Exclusion": {
"Groups": [
"Guests"
]
}
}
]
}
}
}
]
]
}
}
}
9 changes: 4 additions & 5 deletions examples/ConsoleApp/ConsoleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -21,5 +20,5 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
26 changes: 10 additions & 16 deletions examples/ConsoleApp/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
{
"feature_management": {
"feature_flags": [
{
"id": "Beta",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "AccountId",
"parameters": {
"AllowedAccounts": [ "abcdefghijklmnopqrstuvwxyz" ]
}
}
]
"FeatureManagement": {
"Beta": {
"EnabledFor": [
{
"Name": "AccountId",
"Parameters": {
"AllowedAccounts": [ "abcdefghijklmnopqrstuvwxyz" ]
}
}
}
]
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ namespace FeatureFlagDemo.Authentication
///
/// To assign a user, use the following query string structure "?username=JohnDoe&groups=MyGroup1,MyGroup2"
/// </summary>
class QueryStringAuthenticationHandler(IOptionsMonitor<QueryStringAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder) : AuthenticationHandler<QueryStringAuthenticationOptions>(options, logger, encoder)
class QueryStringAuthenticationHandler : AuthenticationHandler<QueryStringAuthenticationOptions>
{
public QueryStringAuthenticationHandler(IOptionsMonitor<QueryStringAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}

protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var identity = new ClaimsIdentity();
Expand All @@ -27,9 +32,9 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
string username = value.First();

identity.AddClaim(new Claim(ClaimTypes.Name, username));
identity.AddClaim(new Claim(System.Security.Claims.ClaimTypes.Name, username));

Logger.LogInformation("Assigning the username {username} to the request.", username);
Logger.LogInformation($"Assigning the username '{username}' to the request.");
}

//
Expand All @@ -43,7 +48,7 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
identity.AddClaim(new Claim(ClaimTypes.Role, group));
}

Logger.LogInformation("Assigning the following groups '{groups}' to the request.", string.Join(", ", groups));
Logger.LogInformation($"Assigning the following groups '{string.Join(", ", groups)}' to the request.");
}

//
Expand Down
4 changes: 2 additions & 2 deletions examples/FeatureFlagDemo/FeatureFlagDemo.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="7.3.0" />
<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="3.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading
Loading