diff --git a/eng/Dependencies.props b/eng/Dependencies.props
index 51d1105d9e2e..18be2fda9f68 100644
--- a/eng/Dependencies.props
+++ b/eng/Dependencies.props
@@ -189,6 +189,7 @@ and are generated based on the last package release.
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 1a5f3a180b9b..dbea555cdc29 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -257,6 +257,7 @@
$(MessagePackVersion)
4.10.0
0.11.2
+ 2.2.1
1.0.2
13.0.1
13.0.4
diff --git a/src/Http/Http.Results/Directory.Build.props b/src/Http/Http.Results/Directory.Build.props
new file mode 100644
index 000000000000..dcd7ca497754
--- /dev/null
+++ b/src/Http/Http.Results/Directory.Build.props
@@ -0,0 +1,7 @@
+
+
+
+
+ $(MSBuildThisFileDirectory)\src
+
+
diff --git a/src/Http/Http.Results/src/Microsoft.AspNetCore.Http.Results.csproj b/src/Http/Http.Results/src/Microsoft.AspNetCore.Http.Results.csproj
index cfa2eb2e0da9..0d9845104cc4 100644
--- a/src/Http/Http.Results/src/Microsoft.AspNetCore.Http.Results.csproj
+++ b/src/Http/Http.Results/src/Microsoft.AspNetCore.Http.Results.csproj
@@ -28,4 +28,16 @@
+
+
+
+
+
+
+
+ TextTemplatingFileGenerator
+ ResultsCache.StatusCodes.cs
+
+
+
diff --git a/src/Http/Http.Results/src/Results.cs b/src/Http/Http.Results/src/Results.cs
index 89b9c12bde7d..35187a07d435 100644
--- a/src/Http/Http.Results/src/Results.cs
+++ b/src/Http/Http.Results/src/Results.cs
@@ -495,7 +495,7 @@ public static IResult RedirectToRoute(string? routeName = null, object? routeVal
/// The status code to set on the response.
/// The created object for the response.
public static IResult StatusCode(int statusCode)
- => new StatusCodeHttpResult(statusCode);
+ => ResultsCache.StatusCode(statusCode);
///
/// Produces a response.
@@ -503,14 +503,14 @@ public static IResult StatusCode(int statusCode)
/// The value to be included in the HTTP response body.
/// The created for the response.
public static IResult NotFound(object? value = null)
- => new NotFoundObjectHttpResult(value);
+ => value is null ? ResultsCache.NotFound : new NotFoundObjectHttpResult(value);
///
/// Produces a response.
///
/// The created for the response.
public static IResult Unauthorized()
- => new UnauthorizedHttpResult();
+ => ResultsCache.Unauthorized;
///
/// Produces a response.
@@ -518,7 +518,7 @@ public static IResult Unauthorized()
/// An error object to be included in the HTTP response body.
/// The created for the response.
public static IResult BadRequest(object? error = null)
- => new BadRequestObjectHttpResult(error);
+ => error is null ? ResultsCache.BadRequest : new BadRequestObjectHttpResult(error);
///
/// Produces a response.
@@ -526,14 +526,14 @@ public static IResult BadRequest(object? error = null)
/// An error object to be included in the HTTP response body.
/// The created for the response.
public static IResult Conflict(object? error = null)
- => new ConflictObjectHttpResult(error);
+ => error is null ? ResultsCache.Conflict : new ConflictObjectHttpResult(error);
///
/// Produces a response.
///
/// The created for the response.
public static IResult NoContent()
- => new NoContentHttpResult();
+ => ResultsCache.NoContent;
///
/// Produces a response.
@@ -541,7 +541,7 @@ public static IResult NoContent()
/// The value to be included in the HTTP response body.
/// The created for the response.
public static IResult Ok(object? value = null)
- => new OkObjectHttpResult(value);
+ => value is null ? ResultsCache.Ok : new OkObjectHttpResult(value);
///
/// Produces a response.
@@ -549,7 +549,7 @@ public static IResult Ok(object? value = null)
/// An error object to be included in the HTTP response body.
/// The created for the response.
public static IResult UnprocessableEntity(object? error = null)
- => new UnprocessableEntityObjectHttpResult(error);
+ => error is null ? ResultsCache.UnprocessableEntity : new UnprocessableEntityObjectHttpResult(error);
///
/// Produces a response.
diff --git a/src/Http/Http.Results/src/ResultsCache.StatusCodes.cs b/src/Http/Http.Results/src/ResultsCache.StatusCodes.cs
new file mode 100644
index 000000000000..4e255cd9449c
--- /dev/null
+++ b/src/Http/Http.Results/src/ResultsCache.StatusCodes.cs
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#nullable enable
+
+using System.CodeDom.Compiler;
+
+namespace Microsoft.AspNetCore.Http;
+
+[GeneratedCode("TextTemplatingFileGenerator", "")]
+internal partial class ResultsCache
+{
+ private static StatusCodeHttpResult? _status101SwitchingProtocols;
+ private static StatusCodeHttpResult? _status102Processing;
+ private static StatusCodeHttpResult? _status200OK;
+ private static StatusCodeHttpResult? _status201Created;
+ private static StatusCodeHttpResult? _status202Accepted;
+ private static StatusCodeHttpResult? _status203NonAuthoritative;
+ private static StatusCodeHttpResult? _status204NoContent;
+ private static StatusCodeHttpResult? _status205ResetContent;
+ private static StatusCodeHttpResult? _status206PartialContent;
+ private static StatusCodeHttpResult? _status207MultiStatus;
+ private static StatusCodeHttpResult? _status208AlreadyReported;
+ private static StatusCodeHttpResult? _status226IMUsed;
+ private static StatusCodeHttpResult? _status300MultipleChoices;
+ private static StatusCodeHttpResult? _status301MovedPermanently;
+ private static StatusCodeHttpResult? _status302Found;
+ private static StatusCodeHttpResult? _status303SeeOther;
+ private static StatusCodeHttpResult? _status304NotModified;
+ private static StatusCodeHttpResult? _status305UseProxy;
+ private static StatusCodeHttpResult? _status306SwitchProxy;
+ private static StatusCodeHttpResult? _status307TemporaryRedirect;
+ private static StatusCodeHttpResult? _status308PermanentRedirect;
+ private static StatusCodeHttpResult? _status400BadRequest;
+ private static StatusCodeHttpResult? _status401Unauthorized;
+ private static StatusCodeHttpResult? _status402PaymentRequired;
+ private static StatusCodeHttpResult? _status403Forbidden;
+ private static StatusCodeHttpResult? _status404NotFound;
+ private static StatusCodeHttpResult? _status405MethodNotAllowed;
+ private static StatusCodeHttpResult? _status406NotAcceptable;
+ private static StatusCodeHttpResult? _status407ProxyAuthenticationRequired;
+ private static StatusCodeHttpResult? _status408RequestTimeout;
+ private static StatusCodeHttpResult? _status409Conflict;
+ private static StatusCodeHttpResult? _status410Gone;
+ private static StatusCodeHttpResult? _status411LengthRequired;
+ private static StatusCodeHttpResult? _status412PreconditionFailed;
+ private static StatusCodeHttpResult? _status413RequestEntityTooLarge;
+ private static StatusCodeHttpResult? _status414RequestUriTooLong;
+ private static StatusCodeHttpResult? _status415UnsupportedMediaType;
+ private static StatusCodeHttpResult? _status416RequestedRangeNotSatisfiable;
+ private static StatusCodeHttpResult? _status417ExpectationFailed;
+ private static StatusCodeHttpResult? _status418ImATeapot;
+ private static StatusCodeHttpResult? _status419AuthenticationTimeout;
+ private static StatusCodeHttpResult? _status421MisdirectedRequest;
+ private static StatusCodeHttpResult? _status422UnprocessableEntity;
+ private static StatusCodeHttpResult? _status423Locked;
+ private static StatusCodeHttpResult? _status424FailedDependency;
+ private static StatusCodeHttpResult? _status426UpgradeRequired;
+ private static StatusCodeHttpResult? _status428PreconditionRequired;
+ private static StatusCodeHttpResult? _status429TooManyRequests;
+ private static StatusCodeHttpResult? _status431RequestHeaderFieldsTooLarge;
+ private static StatusCodeHttpResult? _status451UnavailableForLegalReasons;
+ private static StatusCodeHttpResult? _status500InternalServerError;
+ private static StatusCodeHttpResult? _status501NotImplemented;
+ private static StatusCodeHttpResult? _status502BadGateway;
+ private static StatusCodeHttpResult? _status503ServiceUnavailable;
+ private static StatusCodeHttpResult? _status504GatewayTimeout;
+ private static StatusCodeHttpResult? _status505HttpVersionNotsupported;
+ private static StatusCodeHttpResult? _status506VariantAlsoNegotiates;
+ private static StatusCodeHttpResult? _status507InsufficientStorage;
+ private static StatusCodeHttpResult? _status508LoopDetected;
+ private static StatusCodeHttpResult? _status510NotExtended;
+ private static StatusCodeHttpResult? _status511NetworkAuthenticationRequired;
+
+ internal static StatusCodeHttpResult StatusCode(int statusCode)
+ {
+ if (statusCode is (< 100) or (> 599))
+ {
+ // No HTTP status code assigned outside the 100..599 range
+ // so, it will not be available in the cache
+ return new StatusCodeHttpResult(statusCode);
+ }
+
+ return statusCode switch
+ {
+ StatusCodes.Status101SwitchingProtocols => _status101SwitchingProtocols ??= new(StatusCodes.Status101SwitchingProtocols),
+ StatusCodes.Status102Processing => _status102Processing ??= new(StatusCodes.Status102Processing),
+ StatusCodes.Status200OK => _status200OK ??= new(StatusCodes.Status200OK),
+ StatusCodes.Status201Created => _status201Created ??= new(StatusCodes.Status201Created),
+ StatusCodes.Status202Accepted => _status202Accepted ??= new(StatusCodes.Status202Accepted),
+ StatusCodes.Status203NonAuthoritative => _status203NonAuthoritative ??= new(StatusCodes.Status203NonAuthoritative),
+ StatusCodes.Status204NoContent => _status204NoContent ??= new(StatusCodes.Status204NoContent),
+ StatusCodes.Status205ResetContent => _status205ResetContent ??= new(StatusCodes.Status205ResetContent),
+ StatusCodes.Status206PartialContent => _status206PartialContent ??= new(StatusCodes.Status206PartialContent),
+ StatusCodes.Status207MultiStatus => _status207MultiStatus ??= new(StatusCodes.Status207MultiStatus),
+ StatusCodes.Status208AlreadyReported => _status208AlreadyReported ??= new(StatusCodes.Status208AlreadyReported),
+ StatusCodes.Status226IMUsed => _status226IMUsed ??= new(StatusCodes.Status226IMUsed),
+ StatusCodes.Status300MultipleChoices => _status300MultipleChoices ??= new(StatusCodes.Status300MultipleChoices),
+ StatusCodes.Status301MovedPermanently => _status301MovedPermanently ??= new(StatusCodes.Status301MovedPermanently),
+ StatusCodes.Status302Found => _status302Found ??= new(StatusCodes.Status302Found),
+ StatusCodes.Status303SeeOther => _status303SeeOther ??= new(StatusCodes.Status303SeeOther),
+ StatusCodes.Status304NotModified => _status304NotModified ??= new(StatusCodes.Status304NotModified),
+ StatusCodes.Status305UseProxy => _status305UseProxy ??= new(StatusCodes.Status305UseProxy),
+ StatusCodes.Status306SwitchProxy => _status306SwitchProxy ??= new(StatusCodes.Status306SwitchProxy),
+ StatusCodes.Status307TemporaryRedirect => _status307TemporaryRedirect ??= new(StatusCodes.Status307TemporaryRedirect),
+ StatusCodes.Status308PermanentRedirect => _status308PermanentRedirect ??= new(StatusCodes.Status308PermanentRedirect),
+ StatusCodes.Status400BadRequest => _status400BadRequest ??= new(StatusCodes.Status400BadRequest),
+ StatusCodes.Status401Unauthorized => _status401Unauthorized ??= new(StatusCodes.Status401Unauthorized),
+ StatusCodes.Status402PaymentRequired => _status402PaymentRequired ??= new(StatusCodes.Status402PaymentRequired),
+ StatusCodes.Status403Forbidden => _status403Forbidden ??= new(StatusCodes.Status403Forbidden),
+ StatusCodes.Status404NotFound => _status404NotFound ??= new(StatusCodes.Status404NotFound),
+ StatusCodes.Status405MethodNotAllowed => _status405MethodNotAllowed ??= new(StatusCodes.Status405MethodNotAllowed),
+ StatusCodes.Status406NotAcceptable => _status406NotAcceptable ??= new(StatusCodes.Status406NotAcceptable),
+ StatusCodes.Status407ProxyAuthenticationRequired => _status407ProxyAuthenticationRequired ??= new(StatusCodes.Status407ProxyAuthenticationRequired),
+ StatusCodes.Status408RequestTimeout => _status408RequestTimeout ??= new(StatusCodes.Status408RequestTimeout),
+ StatusCodes.Status409Conflict => _status409Conflict ??= new(StatusCodes.Status409Conflict),
+ StatusCodes.Status410Gone => _status410Gone ??= new(StatusCodes.Status410Gone),
+ StatusCodes.Status411LengthRequired => _status411LengthRequired ??= new(StatusCodes.Status411LengthRequired),
+ StatusCodes.Status412PreconditionFailed => _status412PreconditionFailed ??= new(StatusCodes.Status412PreconditionFailed),
+ StatusCodes.Status413RequestEntityTooLarge => _status413RequestEntityTooLarge ??= new(StatusCodes.Status413RequestEntityTooLarge),
+ StatusCodes.Status414RequestUriTooLong => _status414RequestUriTooLong ??= new(StatusCodes.Status414RequestUriTooLong),
+ StatusCodes.Status415UnsupportedMediaType => _status415UnsupportedMediaType ??= new(StatusCodes.Status415UnsupportedMediaType),
+ StatusCodes.Status416RequestedRangeNotSatisfiable => _status416RequestedRangeNotSatisfiable ??= new(StatusCodes.Status416RequestedRangeNotSatisfiable),
+ StatusCodes.Status417ExpectationFailed => _status417ExpectationFailed ??= new(StatusCodes.Status417ExpectationFailed),
+ StatusCodes.Status418ImATeapot => _status418ImATeapot ??= new(StatusCodes.Status418ImATeapot),
+ StatusCodes.Status419AuthenticationTimeout => _status419AuthenticationTimeout ??= new(StatusCodes.Status419AuthenticationTimeout),
+ StatusCodes.Status421MisdirectedRequest => _status421MisdirectedRequest ??= new(StatusCodes.Status421MisdirectedRequest),
+ StatusCodes.Status422UnprocessableEntity => _status422UnprocessableEntity ??= new(StatusCodes.Status422UnprocessableEntity),
+ StatusCodes.Status423Locked => _status423Locked ??= new(StatusCodes.Status423Locked),
+ StatusCodes.Status424FailedDependency => _status424FailedDependency ??= new(StatusCodes.Status424FailedDependency),
+ StatusCodes.Status426UpgradeRequired => _status426UpgradeRequired ??= new(StatusCodes.Status426UpgradeRequired),
+ StatusCodes.Status428PreconditionRequired => _status428PreconditionRequired ??= new(StatusCodes.Status428PreconditionRequired),
+ StatusCodes.Status429TooManyRequests => _status429TooManyRequests ??= new(StatusCodes.Status429TooManyRequests),
+ StatusCodes.Status431RequestHeaderFieldsTooLarge => _status431RequestHeaderFieldsTooLarge ??= new(StatusCodes.Status431RequestHeaderFieldsTooLarge),
+ StatusCodes.Status451UnavailableForLegalReasons => _status451UnavailableForLegalReasons ??= new(StatusCodes.Status451UnavailableForLegalReasons),
+ StatusCodes.Status500InternalServerError => _status500InternalServerError ??= new(StatusCodes.Status500InternalServerError),
+ StatusCodes.Status501NotImplemented => _status501NotImplemented ??= new(StatusCodes.Status501NotImplemented),
+ StatusCodes.Status502BadGateway => _status502BadGateway ??= new(StatusCodes.Status502BadGateway),
+ StatusCodes.Status503ServiceUnavailable => _status503ServiceUnavailable ??= new(StatusCodes.Status503ServiceUnavailable),
+ StatusCodes.Status504GatewayTimeout => _status504GatewayTimeout ??= new(StatusCodes.Status504GatewayTimeout),
+ StatusCodes.Status505HttpVersionNotsupported => _status505HttpVersionNotsupported ??= new(StatusCodes.Status505HttpVersionNotsupported),
+ StatusCodes.Status506VariantAlsoNegotiates => _status506VariantAlsoNegotiates ??= new(StatusCodes.Status506VariantAlsoNegotiates),
+ StatusCodes.Status507InsufficientStorage => _status507InsufficientStorage ??= new(StatusCodes.Status507InsufficientStorage),
+ StatusCodes.Status508LoopDetected => _status508LoopDetected ??= new(StatusCodes.Status508LoopDetected),
+ StatusCodes.Status510NotExtended => _status510NotExtended ??= new(StatusCodes.Status510NotExtended),
+ StatusCodes.Status511NetworkAuthenticationRequired => _status511NetworkAuthenticationRequired ??= new(StatusCodes.Status511NetworkAuthenticationRequired),
+ _ => new StatusCodeHttpResult(statusCode),
+ };
+ }
+}
diff --git a/src/Http/Http.Results/src/ResultsCache.StatusCodes.tt b/src/Http/Http.Results/src/ResultsCache.StatusCodes.tt
new file mode 100644
index 000000000000..578deef36952
--- /dev/null
+++ b/src/Http/Http.Results/src/ResultsCache.StatusCodes.tt
@@ -0,0 +1,106 @@
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#
+ /// A collection of constants for
+ /// HTTP status codes.
+ var statusCodes = new[]
+ {
+ new { StatusCode = 101, Name = "101SwitchingProtocols"},
+ new { StatusCode = 102, Name = "102Processing"},
+ new { StatusCode = 200, Name = "200OK"},
+ new { StatusCode = 201, Name = "201Created"},
+ new { StatusCode = 202, Name = "202Accepted"},
+ new { StatusCode = 203, Name = "203NonAuthoritative"},
+ new { StatusCode = 204, Name = "204NoContent"},
+ new { StatusCode = 205, Name = "205ResetContent"},
+ new { StatusCode = 206, Name = "206PartialContent"},
+ new { StatusCode = 207, Name = "207MultiStatus"},
+ new { StatusCode = 208, Name = "208AlreadyReported"},
+ new { StatusCode = 226, Name = "226IMUsed"},
+ new { StatusCode = 300, Name = "300MultipleChoices"},
+ new { StatusCode = 301, Name = "301MovedPermanently"},
+ new { StatusCode = 302, Name = "302Found"},
+ new { StatusCode = 303, Name = "303SeeOther"},
+ new { StatusCode = 304, Name = "304NotModified"},
+ new { StatusCode = 305, Name = "305UseProxy"},
+ new { StatusCode = 306, Name = "306SwitchProxy"},
+ new { StatusCode = 307, Name = "307TemporaryRedirect"},
+ new { StatusCode = 308, Name = "308PermanentRedirect"},
+ new { StatusCode = 400, Name = "400BadRequest"},
+ new { StatusCode = 401, Name = "401Unauthorized"},
+ new { StatusCode = 402, Name = "402PaymentRequired"},
+ new { StatusCode = 403, Name = "403Forbidden"},
+ new { StatusCode = 404, Name = "404NotFound"},
+ new { StatusCode = 405, Name = "405MethodNotAllowed"},
+ new { StatusCode = 406, Name = "406NotAcceptable"},
+ new { StatusCode = 407, Name = "407ProxyAuthenticationRequired"},
+ new { StatusCode = 408, Name = "408RequestTimeout"},
+ new { StatusCode = 409, Name = "409Conflict"},
+ new { StatusCode = 410, Name = "410Gone"},
+ new { StatusCode = 411, Name = "411LengthRequired"},
+ new { StatusCode = 412, Name = "412PreconditionFailed"},
+ new { StatusCode = 413, Name = "413RequestEntityTooLarge"},
+ new { StatusCode = 414, Name = "414RequestUriTooLong"},
+ new { StatusCode = 415, Name = "415UnsupportedMediaType"},
+ new { StatusCode = 416, Name = "416RequestedRangeNotSatisfiable"},
+ new { StatusCode = 417, Name = "417ExpectationFailed"},
+ new { StatusCode = 418, Name = "418ImATeapot"},
+ new { StatusCode = 419, Name = "419AuthenticationTimeout"},
+ new { StatusCode = 421, Name = "421MisdirectedRequest"},
+ new { StatusCode = 422, Name = "422UnprocessableEntity"},
+ new { StatusCode = 423, Name = "423Locked"},
+ new { StatusCode = 424, Name = "424FailedDependency"},
+ new { StatusCode = 426, Name = "426UpgradeRequired"},
+ new { StatusCode = 428, Name = "428PreconditionRequired"},
+ new { StatusCode = 429, Name = "429TooManyRequests"},
+ new { StatusCode = 431, Name = "431RequestHeaderFieldsTooLarge"},
+ new { StatusCode = 451, Name = "451UnavailableForLegalReasons"},
+ new { StatusCode = 500, Name = "500InternalServerError"},
+ new { StatusCode = 501, Name = "501NotImplemented"},
+ new { StatusCode = 502, Name = "502BadGateway"},
+ new { StatusCode = 503, Name = "503ServiceUnavailable"},
+ new { StatusCode = 504, Name = "504GatewayTimeout"},
+ new { StatusCode = 505, Name = "505HttpVersionNotsupported"},
+ new { StatusCode = 506, Name = "506VariantAlsoNegotiates"},
+ new { StatusCode = 507, Name = "507InsufficientStorage"},
+ new { StatusCode = 508, Name = "508LoopDetected"},
+ new { StatusCode = 510, Name = "510NotExtended"},
+ new { StatusCode = 511, Name = "511NetworkAuthenticationRequired"},
+ };
+#>
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#nullable enable
+
+using System.CodeDom.Compiler;
+
+namespace Microsoft.AspNetCore.Http;
+
+[GeneratedCode("TextTemplatingFileGenerator", "")]
+internal partial class ResultsCache
+{
+<# foreach (var statusCode in statusCodes) { #>
+ private static StatusCodeHttpResult? _status<#= statusCode.Name #>;
+<# } #>
+
+ internal static StatusCodeHttpResult StatusCode(int statusCode)
+ {
+ if (statusCode is (< 100) or (> 599))
+ {
+ // No HTTP status code assigned outside the 100..599 range
+ // so, it will not be available in the cache
+ return new StatusCodeHttpResult(statusCode);
+ }
+
+ return statusCode switch
+ {
+<# foreach (var statusCode in statusCodes) { #>
+ StatusCodes.Status<#= statusCode.Name #> => _status<#= statusCode.Name #> ??= new(StatusCodes.Status<#= statusCode.Name #>),
+<# } #>
+ _ => new StatusCodeHttpResult(statusCode),
+ };
+ }
+}
diff --git a/src/Http/Http.Results/src/ResultsCache.cs b/src/Http/Http.Results/src/ResultsCache.cs
new file mode 100644
index 000000000000..dcdcaf092fb0
--- /dev/null
+++ b/src/Http/Http.Results/src/ResultsCache.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.Http;
+
+internal static partial class ResultsCache
+{
+ public static NotFoundObjectHttpResult NotFound { get; } = new(null);
+ public static UnauthorizedHttpResult Unauthorized { get; } = new();
+ public static BadRequestObjectHttpResult BadRequest { get; } = new(null);
+ public static ConflictObjectHttpResult Conflict { get; } = new(null);
+ public static NoContentHttpResult NoContent { get; } = new();
+ public static OkObjectHttpResult Ok { get; } = new(null);
+ public static UnprocessableEntityObjectHttpResult UnprocessableEntity { get; } = new(null);
+}
diff --git a/src/Http/Http.Results/test/Microsoft.AspNetCore.Http.Results.Tests.csproj b/src/Http/Http.Results/test/Microsoft.AspNetCore.Http.Results.Tests.csproj
index f59c42ded08a..e89f39527936 100644
--- a/src/Http/Http.Results/test/Microsoft.AspNetCore.Http.Results.Tests.csproj
+++ b/src/Http/Http.Results/test/Microsoft.AspNetCore.Http.Results.Tests.csproj
@@ -1,4 +1,4 @@
-
+
$(DefaultNetCoreTargetFramework)
@@ -8,12 +8,14 @@
+
-
-
+
+
+
diff --git a/src/Http/Http.Results/test/ResultsCacheTests.cs b/src/Http/Http.Results/test/ResultsCacheTests.cs
new file mode 100644
index 000000000000..15593f88fdea
--- /dev/null
+++ b/src/Http/Http.Results/test/ResultsCacheTests.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.Http.Results.Tests;
+
+using Mono.TextTemplating;
+
+public class ResultsCacheTests
+{
+ [Fact]
+ public void GeneratedCodeIsUpToDate()
+ {
+ var currentContentPath = Path.Combine(AppContext.BaseDirectory, "Shared", "GeneratedContent", "ResultsCache.StatusCodes.cs");
+ var templatePath = Path.Combine(AppContext.BaseDirectory, "Shared", "GeneratedContent", "ResultsCache.StatusCodes.tt");
+
+ var generator = new TemplateGenerator();
+ var compiledTemplate = generator.CompileTemplate(File.ReadAllText(templatePath));
+
+ var generatedContent = compiledTemplate.Process();
+ var currentContent = File.ReadAllText(currentContentPath);
+
+ Assert.Equal(currentContent, generatedContent);
+ }
+}
diff --git a/src/Http/README.md b/src/Http/README.md
index b8be410bf8c4..8204a3985644 100644
--- a/src/Http/README.md
+++ b/src/Http/README.md
@@ -25,6 +25,13 @@ The following contains a description of each sub-directory in the `Http` directo
## Development Setup
+To run the code generation using [T4 Text Templates](https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates), you can use an IDE that supports it (eg. Visual Studio or JetBrains Rider) or install the cross-platform open-source dotnet tool [Mono/T4](https://github.com/mono/t4).
+
+```powershell
+> dotnet tool install -g dotnet-t4
+> t4 Http.Results\ResultsCache.StatusCodes.tt
+```
+
### Build
To build this specific project from source, follow the instructions [on building the project](../../docs/BuildFromSource.md#step-3-build-the-repo).