Skip to content

Commit 94b7c9a

Browse files
authored
More IResult Implementations (#32738)
* IResult implementation for SignInResult * IResult implementation for SignOutResult * IResult implementation for ForbidResult * IResult implementation for ChallangeResult * return Task directly instead of async/await.
1 parent 1786ac9 commit 94b7c9a

7 files changed

+237
-23
lines changed

src/Mvc/Mvc.Core/src/ChallengeResult.cs

+17-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
77
using Microsoft.AspNetCore.Authentication;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.Extensions.DependencyInjection;
910
using Microsoft.Extensions.Logging;
1011

@@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc
1314
/// <summary>
1415
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.ChallengeAsync"/>.
1516
/// </summary>
16-
public class ChallengeResult : ActionResult
17+
public class ChallengeResult : ActionResult, IResult
1718
{
1819
/// <summary>
1920
/// Initializes a new instance of <see cref="ChallengeResult"/>.
@@ -90,14 +91,25 @@ public ChallengeResult(IList<string> authenticationSchemes, AuthenticationProper
9091
public AuthenticationProperties? Properties { get; set; }
9192

9293
/// <inheritdoc />
93-
public override async Task ExecuteResultAsync(ActionContext context)
94+
public override Task ExecuteResultAsync(ActionContext context)
9495
{
9596
if (context == null)
9697
{
9798
throw new ArgumentNullException(nameof(context));
9899
}
99100

100-
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
101+
return ExecuteAsync(context.HttpContext);
102+
}
103+
104+
/// <inheritdoc />
105+
Task IResult.ExecuteAsync(HttpContext httpContext)
106+
{
107+
return ExecuteAsync(httpContext);
108+
}
109+
110+
private async Task ExecuteAsync(HttpContext httpContext)
111+
{
112+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
101113
var logger = loggerFactory.CreateLogger<ChallengeResult>();
102114

103115
logger.ChallengeResultExecuting(AuthenticationSchemes);
@@ -106,12 +118,12 @@ public override async Task ExecuteResultAsync(ActionContext context)
106118
{
107119
foreach (var scheme in AuthenticationSchemes)
108120
{
109-
await context.HttpContext.ChallengeAsync(scheme, Properties);
121+
await httpContext.ChallengeAsync(scheme, Properties);
110122
}
111123
}
112124
else
113125
{
114-
await context.HttpContext.ChallengeAsync(Properties);
126+
await httpContext.ChallengeAsync(Properties);
115127
}
116128
}
117129
}

src/Mvc/Mvc.Core/src/ForbidResult.cs

+17-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
77
using Microsoft.AspNetCore.Authentication;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.Extensions.DependencyInjection;
910
using Microsoft.Extensions.Logging;
1011

@@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc
1314
/// <summary>
1415
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.ForbidAsync"/>.
1516
/// </summary>
16-
public class ForbidResult : ActionResult
17+
public class ForbidResult : ActionResult, IResult
1718
{
1819
/// <summary>
1920
/// Initializes a new instance of <see cref="ForbidResult"/>.
@@ -90,14 +91,25 @@ public ForbidResult(IList<string> authenticationSchemes, AuthenticationPropertie
9091
public AuthenticationProperties? Properties { get; set; }
9192

9293
/// <inheritdoc />
93-
public override async Task ExecuteResultAsync(ActionContext context)
94+
public override Task ExecuteResultAsync(ActionContext context)
9495
{
9596
if (context == null)
9697
{
9798
throw new ArgumentNullException(nameof(context));
9899
}
99100

100-
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
101+
return ExecuteAsync(context.HttpContext);
102+
}
103+
104+
/// <inheritdoc />
105+
Task IResult.ExecuteAsync(HttpContext httpContext)
106+
{
107+
return ExecuteAsync(httpContext);
108+
}
109+
110+
private async Task ExecuteAsync(HttpContext httpContext)
111+
{
112+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
101113
var logger = loggerFactory.CreateLogger<ForbidResult>();
102114

103115
logger.ForbidResultExecuting(AuthenticationSchemes);
@@ -106,12 +118,12 @@ public override async Task ExecuteResultAsync(ActionContext context)
106118
{
107119
for (var i = 0; i < AuthenticationSchemes.Count; i++)
108120
{
109-
await context.HttpContext.ForbidAsync(AuthenticationSchemes[i], Properties);
121+
await httpContext.ForbidAsync(AuthenticationSchemes[i], Properties);
110122
}
111123
}
112124
else
113125
{
114-
await context.HttpContext.ForbidAsync(Properties);
126+
await httpContext.ForbidAsync(Properties);
115127
}
116128
}
117129
}

src/Mvc/Mvc.Core/src/SignInResult.cs

+16-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Security.Claims;
66
using System.Threading.Tasks;
77
using Microsoft.AspNetCore.Authentication;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.AspNetCore.Mvc.Core;
910
using Microsoft.Extensions.DependencyInjection;
1011
using Microsoft.Extensions.Logging;
@@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc
1415
/// <summary>
1516
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.SignInAsync"/>.
1617
/// </summary>
17-
public class SignInResult : ActionResult
18+
public class SignInResult : ActionResult, IResult
1819
{
1920
/// <summary>
2021
/// Initializes a new instance of <see cref="SignInResult"/> with the
@@ -78,19 +79,30 @@ public SignInResult(string? authenticationScheme, ClaimsPrincipal principal, Aut
7879
public AuthenticationProperties? Properties { get; set; }
7980

8081
/// <inheritdoc />
81-
public override async Task ExecuteResultAsync(ActionContext context)
82+
public override Task ExecuteResultAsync(ActionContext context)
8283
{
8384
if (context == null)
8485
{
8586
throw new ArgumentNullException(nameof(context));
8687
}
8788

88-
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
89+
return ExecuteAsync(context.HttpContext);
90+
}
91+
92+
/// <inheritdoc />
93+
Task IResult.ExecuteAsync(HttpContext httpContext)
94+
{
95+
return ExecuteAsync(httpContext);
96+
}
97+
98+
private Task ExecuteAsync(HttpContext httpContext)
99+
{
100+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
89101
var logger = loggerFactory.CreateLogger<SignInResult>();
90102

91103
logger.SignInResultExecuting(AuthenticationScheme, Principal);
92104

93-
await context.HttpContext.SignInAsync(AuthenticationScheme, Principal, Properties);
105+
return httpContext.SignInAsync(AuthenticationScheme, Principal, Properties);
94106
}
95107
}
96108
}

src/Mvc/Mvc.Core/src/SignOutResult.cs

+17-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
77
using Microsoft.AspNetCore.Authentication;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.AspNetCore.Mvc.Core;
910
using Microsoft.Extensions.DependencyInjection;
1011
using Microsoft.Extensions.Logging;
@@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc
1415
/// <summary>
1516
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.SignOutAsync"/>.
1617
/// </summary>
17-
public class SignOutResult : ActionResult
18+
public class SignOutResult : ActionResult, IResult
1819
{
1920
/// <summary>
2021
/// Initializes a new instance of <see cref="SignOutResult"/> with the default sign out scheme.
@@ -88,13 +89,24 @@ public SignOutResult(IList<string> authenticationSchemes, AuthenticationProperti
8889
public AuthenticationProperties? Properties { get; set; }
8990

9091
/// <inheritdoc />
91-
public override async Task ExecuteResultAsync(ActionContext context)
92+
public override Task ExecuteResultAsync(ActionContext context)
9293
{
9394
if (context == null)
9495
{
9596
throw new ArgumentNullException(nameof(context));
9697
}
9798

99+
return ExecuteAsync(context.HttpContext);
100+
}
101+
102+
/// <inheritdoc />
103+
Task IResult.ExecuteAsync(HttpContext httpContext)
104+
{
105+
return ExecuteAsync(httpContext);
106+
}
107+
108+
private async Task ExecuteAsync(HttpContext httpContext)
109+
{
98110
if (AuthenticationSchemes == null)
99111
{
100112
throw new InvalidOperationException(
@@ -103,20 +115,20 @@ public override async Task ExecuteResultAsync(ActionContext context)
103115
/* type: */ nameof(SignOutResult)));
104116
}
105117

106-
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
118+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
107119
var logger = loggerFactory.CreateLogger<SignOutResult>();
108120

109121
logger.SignOutResultExecuting(AuthenticationSchemes);
110122

111123
if (AuthenticationSchemes.Count == 0)
112124
{
113-
await context.HttpContext.SignOutAsync(Properties);
125+
await httpContext.SignOutAsync(Properties);
114126
}
115127
else
116128
{
117129
for (var i = 0; i < AuthenticationSchemes.Count; i++)
118130
{
119-
await context.HttpContext.SignOutAsync(AuthenticationSchemes[i], Properties);
131+
await httpContext.SignOutAsync(AuthenticationSchemes[i], Properties);
120132
}
121133
}
122134
}

src/Mvc/Mvc.Core/test/ChallengeResultTest.cs

+40-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc
1717
public class ChallengeResultTest
1818
{
1919
[Fact]
20-
public async Task ChallengeResult_Execute()
20+
public async Task ChallengeResult_ExecuteResultAsync()
2121
{
2222
// Arrange
2323
var result = new ChallengeResult("", null);
@@ -43,7 +43,7 @@ public async Task ChallengeResult_Execute()
4343
}
4444

4545
[Fact]
46-
public async Task ChallengeResult_ExecuteNoSchemes()
46+
public async Task ChallengeResult_ExecuteResultAsync_NoSchemes()
4747
{
4848
// Arrange
4949
var result = new ChallengeResult(new string[] { }, null);
@@ -67,6 +67,43 @@ public async Task ChallengeResult_ExecuteNoSchemes()
6767
auth.Verify(c => c.ChallengeAsync(httpContext.Object, null, null), Times.Exactly(1));
6868
}
6969

70+
[Fact]
71+
public async Task ChallengeResult_ExecuteAsync()
72+
{
73+
// Arrange
74+
var result = new ChallengeResult("", null);
75+
76+
var auth = new Mock<IAuthenticationService>();
77+
78+
var httpContext = new Mock<HttpContext>();
79+
httpContext.SetupGet(c => c.RequestServices)
80+
.Returns(CreateServices().AddSingleton(auth.Object).BuildServiceProvider());
81+
82+
// Act
83+
await ((IResult)result).ExecuteAsync(httpContext.Object);
84+
85+
// Assert
86+
auth.Verify(c => c.ChallengeAsync(httpContext.Object, "", null), Times.Exactly(1));
87+
}
88+
89+
[Fact]
90+
public async Task ChallengeResult_ExecuteAsync_NoSchemes()
91+
{
92+
// Arrange
93+
var result = new ChallengeResult(new string[] { }, null);
94+
95+
var auth = new Mock<IAuthenticationService>();
96+
var httpContext = new Mock<HttpContext>();
97+
httpContext.SetupGet(c => c.RequestServices)
98+
.Returns(CreateServices().AddSingleton(auth.Object).BuildServiceProvider());
99+
100+
// Act
101+
await ((IResult)result).ExecuteAsync(httpContext.Object);
102+
103+
// Assert
104+
auth.Verify(c => c.ChallengeAsync(httpContext.Object, null, null), Times.Exactly(1));
105+
}
106+
70107
private static IServiceCollection CreateServices()
71108
{
72109
var services = new ServiceCollection();
@@ -75,4 +112,4 @@ private static IServiceCollection CreateServices()
75112
return services;
76113
}
77114
}
78-
}
115+
}

src/Mvc/Mvc.Core/test/SignInResultTest.cs

+64
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,70 @@ public async Task ExecuteResultAsync_InvokesSignInAsyncOnConfiguredScheme()
100100
auth.Verify();
101101
}
102102

103+
[Fact]
104+
public async Task ExecuteAsync_InvokesSignInAsyncOnAuthenticationManager()
105+
{
106+
// Arrange
107+
var principal = new ClaimsPrincipal();
108+
var httpContext = new Mock<HttpContext>();
109+
var auth = new Mock<IAuthenticationService>();
110+
auth
111+
.Setup(c => c.SignInAsync(httpContext.Object, "", principal, null))
112+
.Returns(Task.CompletedTask)
113+
.Verifiable();
114+
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
115+
var result = new SignInResult("", principal, null);
116+
117+
// Act
118+
await ((IResult)result).ExecuteAsync(httpContext.Object);
119+
120+
// Assert
121+
auth.Verify();
122+
}
123+
124+
[Fact]
125+
public async Task ExecuteAsync_InvokesSignInAsyncOnAuthenticationManagerWithDefaultScheme()
126+
{
127+
// Arrange
128+
var principal = new ClaimsPrincipal();
129+
var httpContext = new Mock<HttpContext>();
130+
var auth = new Mock<IAuthenticationService>();
131+
auth
132+
.Setup(c => c.SignInAsync(httpContext.Object, null, principal, null))
133+
.Returns(Task.CompletedTask)
134+
.Verifiable();
135+
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
136+
var result = new SignInResult(principal);
137+
138+
// Act
139+
await ((IResult)result).ExecuteAsync(httpContext.Object);
140+
141+
// Assert
142+
auth.Verify();
143+
}
144+
145+
[Fact]
146+
public async Task ExecuteAsync_InvokesSignInAsyncOnConfiguredScheme()
147+
{
148+
// Arrange
149+
var principal = new ClaimsPrincipal();
150+
var authProperties = new AuthenticationProperties();
151+
var httpContext = new Mock<HttpContext>();
152+
var auth = new Mock<IAuthenticationService>();
153+
auth
154+
.Setup(c => c.SignInAsync(httpContext.Object, "Scheme1", principal, authProperties))
155+
.Returns(Task.CompletedTask)
156+
.Verifiable();
157+
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
158+
var result = new SignInResult("Scheme1", principal, authProperties);
159+
160+
// Act
161+
await ((IResult)result).ExecuteAsync(httpContext.Object);
162+
163+
// Assert
164+
auth.Verify();
165+
}
166+
103167
private static IServiceProvider CreateServices(IAuthenticationService auth)
104168
{
105169
return new ServiceCollection()

0 commit comments

Comments
 (0)