Skip to content

Commit b9efadc

Browse files
authored
Separate IResult based results from ActionResults (dotnet#33843)
* Separate IResult based results from ActionResults Fixes dotnet#33729
1 parent ed383aa commit b9efadc

File tree

126 files changed

+7369
-3144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+7369
-3144
lines changed

AspNetCore.sln

+33
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Compon
16261626
EndProject
16271627
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleWebSiteWithWebApplicationBuilderException", "src\Mvc\test\WebSites\SimpleWebSiteWithWebApplicationBuilderException\SimpleWebSiteWithWebApplicationBuilderException.csproj", "{5C641396-7E92-4F5C-A5A1-B4CDF480539B}"
16281628
EndProject
1629+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http.Results", "Http.Results", "{323C3EB6-1D15-4B3D-918D-699D7F64DED9}"
1630+
EndProject
1631+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Results", "src\Http\Http.Results\src\Microsoft.AspNetCore.Http.Results.csproj", "{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}"
1632+
EndProject
1633+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Http.Results.Tests", "src\Http\Http.Results\test\Microsoft.AspNetCore.Http.Results.Tests.csproj", "{F599EAA6-399F-4A91-9B1F-D311305B43D9}"
1634+
EndProject
16291635
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging.W3C.Sample", "src\Middleware\HttpLogging\samples\Logging.W3C.Sample\Logging.W3C.Sample.csproj", "{17459B97-1AA3-4154-83D3-C6BDC9FA3F85}"
16301636
EndProject
16311637
Global
@@ -7747,6 +7753,30 @@ Global
77477753
{5C641396-7E92-4F5C-A5A1-B4CDF480539B}.Release|x64.Build.0 = Release|Any CPU
77487754
{5C641396-7E92-4F5C-A5A1-B4CDF480539B}.Release|x86.ActiveCfg = Release|Any CPU
77497755
{5C641396-7E92-4F5C-A5A1-B4CDF480539B}.Release|x86.Build.0 = Release|Any CPU
7756+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7757+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
7758+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|x64.ActiveCfg = Debug|Any CPU
7759+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|x64.Build.0 = Debug|Any CPU
7760+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|x86.ActiveCfg = Debug|Any CPU
7761+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Debug|x86.Build.0 = Debug|Any CPU
7762+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
7763+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|Any CPU.Build.0 = Release|Any CPU
7764+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|x64.ActiveCfg = Release|Any CPU
7765+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|x64.Build.0 = Release|Any CPU
7766+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|x86.ActiveCfg = Release|Any CPU
7767+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8}.Release|x86.Build.0 = Release|Any CPU
7768+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7769+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
7770+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|x64.ActiveCfg = Debug|Any CPU
7771+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|x64.Build.0 = Debug|Any CPU
7772+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|x86.ActiveCfg = Debug|Any CPU
7773+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Debug|x86.Build.0 = Debug|Any CPU
7774+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
7775+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|Any CPU.Build.0 = Release|Any CPU
7776+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|x64.ActiveCfg = Release|Any CPU
7777+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|x64.Build.0 = Release|Any CPU
7778+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|x86.ActiveCfg = Release|Any CPU
7779+
{F599EAA6-399F-4A91-9B1F-D311305B43D9}.Release|x86.Build.0 = Release|Any CPU
77507780
{17459B97-1AA3-4154-83D3-C6BDC9FA3F85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77517781
{17459B97-1AA3-4154-83D3-C6BDC9FA3F85}.Debug|Any CPU.Build.0 = Debug|Any CPU
77527782
{17459B97-1AA3-4154-83D3-C6BDC9FA3F85}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -8564,6 +8594,9 @@ Global
85648594
{558C46DE-DE16-41D5-8DB7-D6D748E32977} = {3EC71A0E-6515-4A5A-B759-F0BCF1BCFC56}
85658595
{B1AA24A4-5E02-4DC1-B57F-6EB03F91E4DD} = {44963D50-8B58-44E6-918D-788BCB406695}
85668596
{5C641396-7E92-4F5C-A5A1-B4CDF480539B} = {088C37A5-30D2-40FB-B031-D163CFBED006}
8597+
{323C3EB6-1D15-4B3D-918D-699D7F64DED9} = {627BE8B3-59E6-4F1D-8C9C-76B804D41724}
8598+
{092EA9F6-84D4-41EF-A618-BDA50A0E10A8} = {323C3EB6-1D15-4B3D-918D-699D7F64DED9}
8599+
{F599EAA6-399F-4A91-9B1F-D311305B43D9} = {323C3EB6-1D15-4B3D-918D-699D7F64DED9}
85678600
{17459B97-1AA3-4154-83D3-C6BDC9FA3F85} = {022B4B80-E813-4256-8034-11A68146F4EF}
85688601
EndGlobalSection
85698602
GlobalSection(ExtensibilityGlobals) = postSolution

eng/ProjectReferences.props

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Abstractions" ProjectPath="$(RepoRoot)src\Http\Http.Abstractions\src\Microsoft.AspNetCore.Http.Abstractions.csproj" />
3030
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Extensions" ProjectPath="$(RepoRoot)src\Http\Http.Extensions\src\Microsoft.AspNetCore.Http.Extensions.csproj" />
3131
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Features" ProjectPath="$(RepoRoot)src\Http\Http.Features\src\Microsoft.AspNetCore.Http.Features.csproj" />
32+
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Results" ProjectPath="$(RepoRoot)src\Http\Http.Results\src\Microsoft.AspNetCore.Http.Results.csproj" />
3233
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http" ProjectPath="$(RepoRoot)src\Http\Http\src\Microsoft.AspNetCore.Http.csproj" />
3334
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Metadata" ProjectPath="$(RepoRoot)src\Http\Metadata\src\Microsoft.AspNetCore.Metadata.csproj" />
3435
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Owin" ProjectPath="$(RepoRoot)src\Http\Owin\src\Microsoft.AspNetCore.Owin.csproj" />

eng/SharedFramework.Local.props

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Http.Abstractions" />
4949
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Http.Extensions" />
5050
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Http.Features" />
51+
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Http.Results" />
5152
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Http" />
5253
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Routing.Abstractions" />
5354
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Routing" />

src/Framework/test/TestData.cs

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ static TestData()
5555
"Microsoft.AspNetCore.Http.Connections.Common",
5656
"Microsoft.AspNetCore.Http.Extensions",
5757
"Microsoft.AspNetCore.Http.Features",
58+
"Microsoft.AspNetCore.Http.Results",
5859
"Microsoft.AspNetCore.HttpLogging",
5960
"Microsoft.AspNetCore.HttpOverrides",
6061
"Microsoft.AspNetCore.HttpsPolicy",
@@ -188,6 +189,7 @@ static TestData()
188189
{ "Microsoft.AspNetCore.Http.Connections.Common", "6.0.0.0" },
189190
{ "Microsoft.AspNetCore.Http.Extensions", "6.0.0.0" },
190191
{ "Microsoft.AspNetCore.Http.Features", "6.0.0.0" },
192+
{ "Microsoft.AspNetCore.Http.Results", "6.0.0.0" },
191193
{ "Microsoft.AspNetCore.HttpLogging", "6.0.0.0" },
192194
{ "Microsoft.AspNetCore.HttpOverrides", "6.0.0.0" },
193195
{ "Microsoft.AspNetCore.HttpsPolicy", "6.0.0.0" },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.AspNetCore.Routing;
6+
using Microsoft.Extensions.DependencyInjection;
7+
8+
namespace Microsoft.AspNetCore.Http.Result
9+
{
10+
internal sealed class AcceptedAtRouteResult : ObjectResult
11+
{
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="AcceptedAtRouteResult"/> class with the values
14+
/// provided.
15+
/// </summary>
16+
/// <param name="routeValues">The route data to use for generating the URL.</param>
17+
/// <param name="value">The value to format in the entity body.</param>
18+
public AcceptedAtRouteResult(object? routeValues, object? value)
19+
: this(routeName: null, routeValues: routeValues, value: value)
20+
{
21+
}
22+
23+
/// <summary>
24+
/// Initializes a new instance of the <see cref="AcceptedAtRouteResult"/> class with the values
25+
/// provided.
26+
/// </summary>
27+
/// <param name="routeName">The name of the route to use for generating the URL.</param>
28+
/// <param name="routeValues">The route data to use for generating the URL.</param>
29+
/// <param name="value">The value to format in the entity body.</param>
30+
public AcceptedAtRouteResult(
31+
string? routeName,
32+
object? routeValues,
33+
object? value)
34+
: base(value, StatusCodes.Status202Accepted)
35+
{
36+
RouteName = routeName;
37+
RouteValues = new RouteValueDictionary(routeValues);
38+
}
39+
40+
/// <summary>
41+
/// Gets the name of the route to use for generating the URL.
42+
/// </summary>
43+
public string? RouteName { get; }
44+
45+
/// <summary>
46+
/// Gets the route data to use for generating the URL.
47+
/// </summary>
48+
public RouteValueDictionary RouteValues { get; }
49+
50+
/// <inheritdoc />
51+
protected override void OnFormatting(HttpContext context)
52+
{
53+
var linkGenerator = context.RequestServices.GetRequiredService<LinkGenerator>();
54+
var url = linkGenerator.GetUriByAddress(
55+
context,
56+
RouteName,
57+
RouteValues,
58+
fragment: FragmentString.Empty);
59+
60+
if (string.IsNullOrEmpty(url))
61+
{
62+
throw new InvalidOperationException("No route matches the supplied values.");
63+
}
64+
65+
context.Response.Headers.Location = url;
66+
}
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNetCore.Http.Result
7+
{
8+
internal sealed class AcceptedResult : ObjectResult
9+
{
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
12+
/// provided.
13+
/// </summary>
14+
public AcceptedResult()
15+
: base(value: null, StatusCodes.Status202Accepted)
16+
{
17+
}
18+
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
21+
/// provided.
22+
/// </summary>
23+
/// <param name="location">The location at which the status of requested content can be monitored.</param>
24+
/// <param name="value">The value to format in the entity body.</param>
25+
public AcceptedResult(string? location, object? value)
26+
: base(value, StatusCodes.Status202Accepted)
27+
{
28+
Location = location;
29+
}
30+
31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
33+
/// provided.
34+
/// </summary>
35+
/// <param name="locationUri">The location at which the status of requested content can be monitored.</param>
36+
/// <param name="value">The value to format in the entity body.</param>
37+
public AcceptedResult(Uri locationUri, object? value)
38+
: base(value, StatusCodes.Status202Accepted)
39+
{
40+
if (locationUri == null)
41+
{
42+
throw new ArgumentNullException(nameof(locationUri));
43+
}
44+
45+
if (locationUri.IsAbsoluteUri)
46+
{
47+
Location = locationUri.AbsoluteUri;
48+
}
49+
else
50+
{
51+
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
52+
}
53+
}
54+
55+
/// <summary>
56+
/// Gets or sets the location at which the status of the requested content can be monitored.
57+
/// </summary>
58+
public string? Location { get; set; }
59+
60+
/// <inheritdoc />
61+
protected override void OnFormatting(HttpContext context)
62+
{
63+
if (context == null)
64+
{
65+
throw new ArgumentNullException(nameof(context));
66+
}
67+
68+
if (!string.IsNullOrEmpty(Location))
69+
{
70+
context.Response.Headers.Location = Location;
71+
}
72+
}
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNetCore.Http.Result
5+
{
6+
internal sealed class BadRequestObjectResult : ObjectResult
7+
{
8+
public BadRequestObjectResult(object? error)
9+
: base(error, StatusCodes.Status400BadRequest)
10+
{
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNetCore.Http.Result
5+
{
6+
internal sealed class BadRequestResult : StatusCodeResult
7+
{
8+
public BadRequestResult() : base(StatusCodes.Status400BadRequest)
9+
{
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Authentication;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Logging;
11+
12+
namespace Microsoft.AspNetCore.Http.Result
13+
{
14+
/// <summary>
15+
/// An <see cref="IResult"/> that on execution invokes <see cref="M:HttpContext.ChallengeAsync"/>.
16+
/// </summary>
17+
internal sealed partial class ChallengeResult : IResult
18+
{
19+
/// <summary>
20+
/// Initializes a new instance of <see cref="ChallengeResult"/>.
21+
/// </summary>
22+
public ChallengeResult()
23+
: this(Array.Empty<string>())
24+
{
25+
}
26+
27+
/// <summary>
28+
/// Initializes a new instance of <see cref="ChallengeResult"/> with the
29+
/// specified authentication scheme.
30+
/// </summary>
31+
/// <param name="authenticationScheme">The authentication scheme to challenge.</param>
32+
public ChallengeResult(string authenticationScheme)
33+
: this(new[] { authenticationScheme })
34+
{
35+
}
36+
37+
/// <summary>
38+
/// Initializes a new instance of <see cref="ChallengeResult"/> with the
39+
/// specified authentication schemes.
40+
/// </summary>
41+
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
42+
public ChallengeResult(IList<string> authenticationSchemes)
43+
: this(authenticationSchemes, properties: null)
44+
{
45+
}
46+
47+
/// <summary>
48+
/// Initializes a new instance of <see cref="ChallengeResult"/> with the
49+
/// specified <paramref name="properties"/>.
50+
/// </summary>
51+
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
52+
/// challenge.</param>
53+
public ChallengeResult(AuthenticationProperties? properties)
54+
: this(Array.Empty<string>(), properties)
55+
{
56+
}
57+
58+
/// <summary>
59+
/// Initializes a new instance of <see cref="ChallengeResult"/> with the
60+
/// specified authentication scheme and <paramref name="properties"/>.
61+
/// </summary>
62+
/// <param name="authenticationScheme">The authentication schemes to challenge.</param>
63+
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
64+
/// challenge.</param>
65+
public ChallengeResult(string authenticationScheme, AuthenticationProperties? properties)
66+
: this(new[] { authenticationScheme }, properties)
67+
{
68+
}
69+
70+
/// <summary>
71+
/// Initializes a new instance of <see cref="ChallengeResult"/> with the
72+
/// specified authentication schemes and <paramref name="properties"/>.
73+
/// </summary>
74+
/// <param name="authenticationSchemes">The authentication scheme to challenge.</param>
75+
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
76+
/// challenge.</param>
77+
public ChallengeResult(IList<string> authenticationSchemes, AuthenticationProperties? properties)
78+
{
79+
AuthenticationSchemes = authenticationSchemes;
80+
Properties = properties;
81+
}
82+
83+
public IList<string> AuthenticationSchemes { get; init; } = Array.Empty<string>();
84+
85+
public AuthenticationProperties? Properties { get; init; }
86+
87+
public async Task ExecuteAsync(HttpContext httpContext)
88+
{
89+
var logger = httpContext.RequestServices.GetRequiredService<ILogger<ChallengeResult>>();
90+
91+
Log.ChallengeResultExecuting(logger, AuthenticationSchemes);
92+
93+
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
94+
{
95+
foreach (var scheme in AuthenticationSchemes)
96+
{
97+
await httpContext.ChallengeAsync(scheme, Properties);
98+
}
99+
}
100+
else
101+
{
102+
await httpContext.ChallengeAsync(Properties);
103+
}
104+
}
105+
106+
private static partial class Log
107+
{
108+
public static void ChallengeResultExecuting(ILogger logger, IList<string> authenticationSchemes)
109+
{
110+
if (logger.IsEnabled(LogLevel.Information))
111+
{
112+
ChallengeResultExecuting(logger, authenticationSchemes.ToArray());
113+
}
114+
}
115+
116+
[LoggerMessage(1, LogLevel.Information, "Executing ChallengeResult with authentication schemes ({Schemes}).", EventName = "ChallengeResultExecuting", SkipEnabledCheck = true)]
117+
private static partial void ChallengeResultExecuting(ILogger logger, string[] schemes);
118+
}
119+
}
120+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNetCore.Http.Result
5+
{
6+
internal sealed class ConflictObjectResult : ObjectResult
7+
{
8+
public ConflictObjectResult(object? error) :
9+
base(error, StatusCodes.Status409Conflict)
10+
{
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)