diff --git a/src/Components/Components/src/Routing/RegexConstraintSupport.cs b/src/Components/Components/src/Routing/RegexConstraintSupport.cs
index 47210593b779..ad63c2ceeb3c 100644
--- a/src/Components/Components/src/Routing/RegexConstraintSupport.cs
+++ b/src/Components/Components/src/Routing/RegexConstraintSupport.cs
@@ -10,6 +10,6 @@ internal static class RegexConstraintSupport
// until the context switch flows to the runtime.
// This value gets updated by the linker when the app is trimmed, so the code will always be removed from
// webassembly unless the switch is enabled.
- public static bool IsEnabled =>
+ public static bool IsEnabled { get; } =
AppContext.TryGetSwitch("Microsoft.AspNetCore.Components.Routing.RegexConstraintSupport", out var enabled) && enabled;
}
diff --git a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj b/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj
index 25a12fa2bdb9..6a5a2cc2d042 100644
--- a/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj
+++ b/src/Components/Components/test/Microsoft.AspNetCore.Components.Tests.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Components/Components/test/RendererTest.cs b/src/Components/Components/test/RendererTest.cs
index b672dcaf867a..8d9fa1b04c24 100644
--- a/src/Components/Components/test/RendererTest.cs
+++ b/src/Components/Components/test/RendererTest.cs
@@ -12,6 +12,7 @@
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.AspNetCore.InternalTesting;
+using Microsoft.DotNet.RemoteExecutor;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Components.Test;
@@ -4981,13 +4982,18 @@ public async Task DisposeAsyncCallsComponentDisposeAsyncOnSyncContext()
Assert.True(wasOnSyncContext);
}
- [Fact]
- public async Task NoHotReloadListenersAreRegistered_WhenHotReloadIsDisabled()
+ [ConditionalFact]
+ [RemoteExecutionSupported]
+ public void NoHotReloadListenersAreRegistered_WhenHotReloadIsDisabled()
{
- // Arrange
- try
+ var options = new RemoteInvokeOptions();
+ options.RuntimeConfigurationOptions.Add("System.Reflection.Metadata.MetadataUpdater.IsSupported", "false");
+
+ using var remoteHandle = RemoteExecutor.Invoke(static async () =>
{
+ // Set the switch before any code triggers HotReloadManager type initialization.
AppContext.SetSwitch("System.Reflection.Metadata.MetadataUpdater.IsSupported", false);
+
await using var renderer = new TestRenderer();
var hotReloadManager = new HotReloadManager();
renderer.HotReloadManager = hotReloadManager;
@@ -4998,17 +5004,12 @@ public async Task NoHotReloadListenersAreRegistered_WhenHotReloadIsDisabled()
builder.CloseElement();
});
- // Act
var componentId = renderer.AssignRootComponentId(component);
component.TriggerRender();
Assert.False(hotReloadManager.IsSubscribedTo);
await renderer.DisposeAsync();
- }
- finally
- {
- AppContext.SetSwitch("System.Reflection.Metadata.MetadataUpdater.IsSupported", true);
- }
+ }, options);
}
[Fact]
diff --git a/src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs b/src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs
index 5c2d42fedd24..ff6310f8f8a3 100644
--- a/src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs
+++ b/src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs
@@ -10,10 +10,12 @@ internal sealed class HttpNavigationManager : NavigationManager, IHostEnvironmen
{
private const string _disableThrowNavigationException = "Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException";
- [FeatureSwitchDefinition(_disableThrowNavigationException)]
- private static bool _throwNavigationException =>
+ private static readonly bool s_throwNavigationException =
!AppContext.TryGetSwitch(_disableThrowNavigationException, out var switchValue) || !switchValue;
+ [FeatureSwitchDefinition(_disableThrowNavigationException)]
+ private static bool _throwNavigationException => s_throwNavigationException;
+
private Func? _onNavigateTo;
void IHostEnvironmentNavigationManager.Initialize(string baseUri, string uri) => Initialize(baseUri, uri);
diff --git a/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs b/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs
index 6b5bc359d49d..9b120cc48bbe 100644
--- a/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs
+++ b/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs
@@ -22,6 +22,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.InternalTesting;
+using Microsoft.DotNet.RemoteExecutor;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
@@ -982,62 +983,72 @@ public async Task Rendering_ComponentWithJsInteropThrows()
exception.Message);
}
- [Theory]
+ [ConditionalTheory]
+ [RemoteExecutionSupported]
[InlineData(true)]
[InlineData(false)]
- public async Task UriHelperRedirect_ThrowsInvalidOperationException_WhenResponseHasAlreadyStarted(bool allowException)
+ public void UriHelperRedirect_ThrowsInvalidOperationException_WhenResponseHasAlreadyStarted(bool allowException)
{
- AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: !allowException);
- // Arrange
- var ctx = new DefaultHttpContext();
- ctx.Request.Scheme = "http";
- ctx.Request.Host = new HostString("localhost");
- ctx.Request.PathBase = "/base";
- ctx.Request.Path = "/path";
- ctx.Request.QueryString = new QueryString("?query=value");
- ctx.Response.Body = new MemoryStream();
- var responseMock = new Mock();
- responseMock.Setup(r => r.HasStarted).Returns(true);
- ctx.Features.Set(responseMock.Object);
- var httpContext = GetHttpContext(ctx);
- string redirectUri = "http://localhost/redirect";
+ var options = new RemoteInvokeOptions();
+ options.RuntimeConfigurationOptions.Add(
+ "Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException",
+ (!allowException).ToString().ToLowerInvariant());
- // Act
- if (allowException)
+ using var remoteHandle = RemoteExecutor.Invoke(static async (allowExceptionStr) =>
{
- var exception = await Assert.ThrowsAsync(async () => await renderer.PrerenderComponentAsync(
- httpContext,
- typeof(RedirectComponent),
- null,
- ParameterView.FromDictionary(new Dictionary
- {
- { "RedirectUri", redirectUri }
- })));
-
- Assert.Equal("A navigation command was attempted during prerendering after the server already started sending the response. " +
- "Navigation commands can not be issued during server-side prerendering after the response from the server has started. Applications must buffer the" +
- "response and avoid using features like FlushAsync() before all components on the page have been rendered to prevent failed navigation commands.",
- exception.Message);
- }
- else
- {
- await renderer.PrerenderComponentAsync(
- httpContext,
- typeof(RedirectComponent),
- null,
- ParameterView.FromDictionary(new Dictionary
- {
- { "RedirectUri", redirectUri }
- }));
- // read the custom element from the response body
- httpContext.Response.Body.Position = 0;
- var reader = new StreamReader(httpContext.Response.Body);
- var output = await reader.ReadToEndAsync();
-
- // Assert that the output contains expected navigation instructions.
- var pattern = "^.*<\\/template><\\/blazor-ssr-end><\\/blazor-ssr>$";
- Assert.Matches(pattern, output);
- }
+ var allowException = bool.Parse(allowExceptionStr);
+ var services = CreateDefaultServiceCollection().BuildServiceProvider();
+ var renderer = new TestEndpointHtmlRenderer(services, NullLoggerFactory.Instance);
+
+ var ctx = new DefaultHttpContext();
+ ctx.Request.Scheme = "http";
+ ctx.Request.Host = new HostString("localhost");
+ ctx.Request.PathBase = "/base";
+ ctx.Request.Path = "/path";
+ ctx.Request.QueryString = new QueryString("?query=value");
+ ctx.Response.Body = new MemoryStream();
+ ctx.RequestServices = services;
+ var responseMock = new Mock();
+ responseMock.Setup(r => r.HasStarted).Returns(true);
+ ctx.Features.Set(responseMock.Object);
+ string redirectUri = "http://localhost/redirect";
+
+ if (allowException)
+ {
+ var exception = await Assert.ThrowsAsync(async () => await renderer.PrerenderComponentAsync(
+ ctx,
+ typeof(RedirectComponent),
+ null,
+ ParameterView.FromDictionary(new Dictionary
+ {
+ { "RedirectUri", redirectUri }
+ })));
+
+ Assert.Equal("A navigation command was attempted during prerendering after the server already started sending the response. " +
+ "Navigation commands can not be issued during server-side prerendering after the response from the server has started. Applications must buffer the" +
+ "response and avoid using features like FlushAsync() before all components on the page have been rendered to prevent failed navigation commands.",
+ exception.Message);
+ }
+ else
+ {
+ await renderer.PrerenderComponentAsync(
+ ctx,
+ typeof(RedirectComponent),
+ null,
+ ParameterView.FromDictionary(new Dictionary
+ {
+ { "RedirectUri", redirectUri }
+ }));
+ // read the custom element from the response body
+ ctx.Response.Body.Position = 0;
+ var reader = new StreamReader(ctx.Response.Body);
+ var output = await reader.ReadToEndAsync();
+
+ // Assert that the output contains expected navigation instructions.
+ var pattern = "^.*<\\/template><\\/blazor-ssr-end><\\/blazor-ssr>$";
+ Assert.Matches(pattern, output);
+ }
+ }, allowException.ToString(), options);
}
[Fact]
@@ -1343,7 +1354,7 @@ public async Task RenderMode_CanRenderInteractiveComponents()
lines[0] = AssertAndStripBrowserConfiguration(lines[0]);
var serverMarkerMatch = Regex.Match(lines[0], PrerenderedComponentPattern);
var serverNonPrerenderedMarkerMatch = Regex.Match(lines[1], ComponentPattern);
-
+
var webAssemblyMarkerMatch = Regex.Match(lines[2], PrerenderedComponentPattern);
var webAssemblyNonPrerenderedMarkerMatch = Regex.Match(lines[3], ComponentPattern);
diff --git a/src/Components/Endpoints/test/Microsoft.AspNetCore.Components.Endpoints.Tests.csproj b/src/Components/Endpoints/test/Microsoft.AspNetCore.Components.Endpoints.Tests.csproj
index c9e5d41f10d3..31e2630e55f7 100644
--- a/src/Components/Endpoints/test/Microsoft.AspNetCore.Components.Endpoints.Tests.csproj
+++ b/src/Components/Endpoints/test/Microsoft.AspNetCore.Components.Endpoints.Tests.csproj
@@ -28,6 +28,7 @@
+
diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGridFeatureFlags.cs b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGridFeatureFlags.cs
index 1c91fe421ac1..a0165dcc2e63 100644
--- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGridFeatureFlags.cs
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGridFeatureFlags.cs
@@ -1,10 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace Microsoft.AspNetCore.Components.QuickGrid;
internal static class QuickGridFeatureFlags
{
- internal static bool EnableUrlBasedQuickGridNavigationAndSorting =>
- !AppContext.TryGetSwitch("Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting", out var isEnabled) || isEnabled;
+ private const string EnableUrlBasedNavigationSwitchName =
+ "Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting";
+
+#pragma warning disable IDE0044
+ private static bool s_enableUrlBasedQuickGridNavigationAndSorting =
+ !AppContext.TryGetSwitch(EnableUrlBasedNavigationSwitchName, out var isEnabled) || isEnabled;
+#pragma warning restore IDE0044
+
+ [FeatureSwitchDefinition(EnableUrlBasedNavigationSwitchName)]
+ internal static bool EnableUrlBasedQuickGridNavigationAndSorting => s_enableUrlBasedQuickGridNavigationAndSorting;
}
diff --git a/src/Components/Server/src/Circuits/RemoteNavigationManager.cs b/src/Components/Server/src/Circuits/RemoteNavigationManager.cs
index 2100ef3a7a16..f329f074084e 100644
--- a/src/Components/Server/src/Circuits/RemoteNavigationManager.cs
+++ b/src/Components/Server/src/Circuits/RemoteNavigationManager.cs
@@ -20,7 +20,7 @@ internal sealed partial class RemoteNavigationManager : NavigationManager, IHost
private const string _disableThrowNavigationException = "Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException";
[FeatureSwitchDefinition(_disableThrowNavigationException)]
- private static bool _throwNavigationException =>
+ private static bool _throwNavigationException { get; } =
!AppContext.TryGetSwitch(_disableThrowNavigationException, out var switchValue) || !switchValue;
private Func? _onNavigateTo;
diff --git a/src/Components/Shared/src/HotReloadManager.cs b/src/Components/Shared/src/HotReloadManager.cs
index ab01a8f04f39..30dd80f6c03a 100644
--- a/src/Components/Shared/src/HotReloadManager.cs
+++ b/src/Components/Shared/src/HotReloadManager.cs
@@ -13,10 +13,12 @@ internal sealed class HotReloadManager
{
public static readonly HotReloadManager Default = new();
- [FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")]
- internal static bool IsSupported =>
+ private static readonly bool s_isSupported =
AppContext.TryGetSwitch("System.Reflection.Metadata.MetadataUpdater.IsSupported", out bool isSupported) ? isSupported : true;
+ [FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")]
+ internal static bool IsSupported => s_isSupported;
+
///
/// Gets a value that determines if OnDeltaApplied is subscribed to.
///
diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs
index 220260c9066c..f87786a3e9e7 100644
--- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs
+++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs
@@ -31,14 +31,15 @@ public RazorComponentEndpointsStartup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
- if (Configuration.GetValue("DisableUrlDrivenNavigation"))
- {
- AppContext.SetSwitch("Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting", false);
- }
- else
- {
- AppContext.SetSwitch("Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting", true);
- }
+ var enableUrlNavigation = !Configuration.GetValue("DisableUrlDrivenNavigation");
+ AppContext.SetSwitch("Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting", enableUrlNavigation);
+
+ // Also update the cached field in QuickGridFeatureFlags, since it captures the AppContext
+ // switch value once at static initialization and won't see subsequent AppContext changes.
+ var featureFlagsType = typeof(Microsoft.AspNetCore.Components.QuickGrid.QuickGrid<>).Assembly
+ .GetType("Microsoft.AspNetCore.Components.QuickGrid.QuickGridFeatureFlags");
+ featureFlagsType?.GetField("s_enableUrlBasedQuickGridNavigationAndSorting", BindingFlags.Static | BindingFlags.NonPublic)
+ ?.SetValue(null, enableUrlNavigation);
services.AddValidation();
diff --git a/src/Identity/Core/src/SignInManager.cs b/src/Identity/Core/src/SignInManager.cs
index b449d6b7fb0a..491dabfcae61 100644
--- a/src/Identity/Core/src/SignInManager.cs
+++ b/src/Identity/Core/src/SignInManager.cs
@@ -26,6 +26,9 @@ public class SignInManager where TUser : class
private const string PasskeyOperationKey = "PasskeyOperation";
private const string PasskeyStateKey = "PasskeyState";
+ private static readonly bool AlwaysResetLockoutOnSuccess =
+ AppContext.TryGetSwitch("Microsoft.AspNetCore.Identity.CheckPasswordSignInAlwaysResetLockoutOnSuccess", out var enabled) && enabled;
+
private readonly IHttpContextAccessor _contextAccessor;
private readonly IAuthenticationSchemeProvider _schemes;
private readonly IUserConfirmation _confirmation;
@@ -475,7 +478,7 @@ private async Task CheckPasswordSignInCoreAsync(TUser user, string
if (await UserManager.CheckPasswordAsync(user, password))
{
- var alwaysLockout = AppContext.TryGetSwitch("Microsoft.AspNetCore.Identity.CheckPasswordSignInAlwaysResetLockoutOnSuccess", out var enabled) && enabled;
+ var alwaysLockout = AlwaysResetLockoutOnSuccess;
// Only reset the lockout when not in quirks mode if either TFA is not enabled or the client is remembered for TFA.
if (alwaysLockout || !await IsTwoFactorEnabledAsync(user) || await IsTwoFactorClientRememberedAsync(user))
{
diff --git a/src/Mvc/Mvc.ViewFeatures/src/DefaultEditorTemplates.cs b/src/Mvc/Mvc.ViewFeatures/src/DefaultEditorTemplates.cs
index 72b1f3b1fdd3..2033d186f469 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/DefaultEditorTemplates.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/DefaultEditorTemplates.cs
@@ -19,6 +19,7 @@ internal static class DefaultEditorTemplates
{
private const string HtmlAttributeKey = "htmlAttributes";
private const string UsePasswordValue = "Switch.Microsoft.AspNetCore.Mvc.UsePasswordValue";
+ private static readonly bool _usePasswordValue = AppContext.TryGetSwitch(UsePasswordValue, out var enabled) && enabled;
public static IHtmlContent BooleanTemplate(IHtmlHelper htmlHelper)
{
@@ -312,7 +313,7 @@ public static IHtmlContent ObjectTemplate(IHtmlHelper htmlHelper)
public static IHtmlContent PasswordTemplate(IHtmlHelper htmlHelper)
{
object value = null;
- if (AppContext.TryGetSwitch(UsePasswordValue, out var usePasswordValue) && usePasswordValue)
+ if (_usePasswordValue)
{
value = htmlHelper.ViewData.TemplateInfo.FormattedModelValue;
}
diff --git a/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs b/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs
index 19a5a2927927..63c5478fcb6f 100644
--- a/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs
+++ b/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs
@@ -28,6 +28,7 @@ public class AuthorizationMiddleware
{
// AppContext switch used to control whether HttpContext or endpoint is passed as a resource to AuthZ
private const string SuppressUseHttpContextAsAuthorizationResource = "Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource";
+ private static readonly bool _suppressUseHttpContextAsAuthorizationResource = AppContext.TryGetSwitch(SuppressUseHttpContextAsAuthorizationResource, out var enabled) && enabled;
// Property key is used by Endpoint routing to determine if Authorization has run
private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked";
@@ -181,7 +182,7 @@ public async Task Invoke(HttpContext context)
}
object? resource;
- if (AppContext.TryGetSwitch(SuppressUseHttpContextAsAuthorizationResource, out var useEndpointAsResource) && useEndpointAsResource)
+ if (_suppressUseHttpContextAsAuthorizationResource)
{
resource = endpoint;
}
diff --git a/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs b/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs
index 1750d8aaac17..99fd8eaf30eb 100644
--- a/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs
+++ b/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs
@@ -14,6 +14,8 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
+using Microsoft.AspNetCore.InternalTesting;
+using Microsoft.DotNet.RemoteExecutor;
using Moq;
namespace Microsoft.AspNetCore.Authorization.Test;
@@ -290,7 +292,7 @@ public async Task UseAuthorizationUsesCache()
var endpoint = CreateEndpoint(new AuthorizeAttribute("whatever"), new ReqAttribute(req));
var services = new ServiceCollection()
.AddAuthorization()
- .AddSingleton(policyProvider.Object)
+ .AddSingleton(policyProvider.Object)
.AddLogging()
.AddSingleton(CreateDataSource(endpoint)).BuildServiceProvider();
@@ -671,31 +673,60 @@ public async Task AuthZResourceCanBeHttpContextAndHaveEndpoint()
Assert.Equal(endpoint, resource.GetEndpoint());
}
- [Fact]
- public async Task AuthZResourceShouldBeEndpointByDefaultWithCompatSwitch()
+ [ConditionalFact]
+ [RemoteExecutionSupported]
+ public void AuthZResourceShouldBeEndpointByDefaultWithCompatSwitch()
{
- AppContext.SetSwitch("Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource", isEnabled: true);
+ var options = new RemoteInvokeOptions();
+ options.RuntimeConfigurationOptions.Add("Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource", "true");
- // Arrange
- object resource = null;
- var policy = new AuthorizationPolicyBuilder().RequireAssertion(c =>
+ using var remoteHandle = RemoteExecutor.Invoke(static async () =>
{
- resource = c.Resource;
- return true;
- }).Build();
- var policyProvider = new Mock();
- policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
- var next = new TestRequestDelegate();
+ object resource = null;
+ var policy = new AuthorizationPolicyBuilder().RequireAssertion(c =>
+ {
+ resource = c.Resource;
+ return true;
+ }).Build();
+ var policyProvider = new Mock();
+ policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
+
+ var services = new ServiceCollection().BuildServiceProvider();
+ var next = new RequestDelegate(context => Task.CompletedTask);
+ var middleware = new AuthorizationMiddleware(next, policyProvider.Object, services);
+
+ var endpoint = new Endpoint(context => Task.CompletedTask, new EndpointMetadataCollection(new AuthorizeAttribute()), "Test endpoint");
+
+ var basicPrincipal = new ClaimsPrincipal(
+ new ClaimsIdentity(
+ new Claim[]
+ {
+ new Claim("Permission", "CanViewPage"),
+ new Claim(ClaimTypes.Role, "Administrator"),
+ new Claim(ClaimTypes.Role, "User"),
+ new Claim(ClaimTypes.NameIdentifier, "John")
+ },
+ "Basic"));
- var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
- var endpoint = CreateEndpoint(new AuthorizeAttribute());
- var context = GetHttpContext(endpoint: endpoint);
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(Mock.Of());
+ serviceCollection.AddTransient();
+ serviceCollection.AddOptions();
+ serviceCollection.AddLogging();
+ serviceCollection.AddAuthorization();
+ var serviceProvider = serviceCollection.BuildServiceProvider();
- // Act
- await middleware.Invoke(context);
+ var httpContext = new DefaultHttpContext();
+ httpContext.SetEndpoint(endpoint);
+ httpContext.RequestServices = serviceProvider;
+ httpContext.User = basicPrincipal;
- // Assert
- Assert.Equal(endpoint, resource);
+ // Act
+ await middleware.Invoke(httpContext);
+
+ // Assert
+ Assert.Equal(endpoint, resource);
+ }, options);
}
[Fact]
diff --git a/src/Security/Authorization/test/Microsoft.AspNetCore.Authorization.Test.csproj b/src/Security/Authorization/test/Microsoft.AspNetCore.Authorization.Test.csproj
index 8bc06ef33452..e6a17f224e46 100644
--- a/src/Security/Authorization/test/Microsoft.AspNetCore.Authorization.Test.csproj
+++ b/src/Security/Authorization/test/Microsoft.AspNetCore.Authorization.Test.csproj
@@ -34,6 +34,7 @@
+