/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Http/Http.Results/test/HttpResultsHelperTests.cs
320 строк
10 KB
Youssef Victor
Preserve application/problem+json and application/problem+xml when using ProducesAttribute (#66461)
27 апр 2026, 17:19
Не верифицирован
27 апр 2026, 17:19
508f4bb
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Http.Json; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Http.HttpResults; public partial class HttpResultsHelperTests { [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_ForValueTypes(bool useJsonContext) { // Arrange var value = new TodoStruct() { Id = 1, IsComplete = true, Name = "Write even more tests!", }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<TodoStruct>(responseBodyStream.ToArray(), serializerOptions); Assert.Equal("Write even more tests!", body!.Name); Assert.True(body!.IsComplete); } [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_ForReferenceTypes(bool useJsonContext) { // Arrange var value = new Todo() { Id = 1, IsComplete = true, Name = "Write even more tests!", }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<Todo>(responseBodyStream.ToArray(), serializerOptions); Assert.NotNull(body); Assert.Equal("Write even more tests!", body!.Name); Assert.True(body!.IsComplete); } [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_ForChildTypes(bool useJsonContext) { // Arrange var value = new TodoChild() { Id = 1, IsComplete = true, Name = "Write even more tests!", Child = "With type hierarchies!" }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<TodoChild>(responseBodyStream.ToArray(), serializerOptions); Assert.NotNull(body); Assert.Equal("Write even more tests!", body!.Name); Assert.True(body!.IsComplete); Assert.Equal("With type hierarchies!", body!.Child); } [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_UsingBaseType_ForChildTypes(bool useJsonContext) { // Arrange var value = new TodoChild() { Id = 1, IsComplete = true, Name = "Write even more tests!", Child = "With type hierarchies!" }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync<Todo>(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<TodoChild>(responseBodyStream.ToArray(), serializerOptions); Assert.NotNull(body); Assert.Equal("Write even more tests!", body!.Name); Assert.True(body!.IsComplete); Assert.Equal("With type hierarchies!", body!.Child); } [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_UsingBaseType_ForChildTypes_WithJsonPolymorphism(bool useJsonContext) { // Arrange var value = new TodoJsonChild() { Id = 1, IsComplete = true, Name = "Write even more tests!", Child = "With type hierarchies!" }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync<JsonTodo>(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<TodoJsonChild>(responseBodyStream.ToArray(), serializerOptions); Assert.NotNull(body); Assert.Equal("Write even more tests!", body!.Name); Assert.True(body!.IsComplete); Assert.Equal("With type hierarchies!", body!.Child); } [Theory] [InlineData(true)] [InlineData(false)] public async Task WriteResultAsJsonAsync_Works_UsingUnspeakableType(bool useJsonContext) { // Arrange var value = GetTodosAsync(); var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; if (useJsonContext) { serializerOptions.TypeInfoResolver = TestJsonContext.Default; } // Act await HttpResultsHelper.WriteResultAsJsonAsync(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<JsonTodo[]>(responseBodyStream.ToArray(), serializerOptions); Assert.Equal(3, body.Length); var one = Assert.IsType<JsonTodo>(body[0]); Assert.Equal(1, one.Id); Assert.True(one.IsComplete); Assert.Equal("One", one.Name); var two = Assert.IsType<JsonTodo>(body[1]); Assert.Equal(2, two.Id); Assert.False(two.IsComplete); Assert.Equal("Two", two.Name); var three = Assert.IsType<TodoJsonChild>(body[2]); Assert.Equal(3, three.Id); Assert.True(three.IsComplete); Assert.Equal("Three", three.Name); Assert.Equal("ThreeChild", three.Child); } [Fact] public async Task WriteResultAsJsonAsync_SetsProblemJsonContentType_ForProblemDetails() { const string Detail = "Explanation of something went wrong :'("; // Arrange var value = new ProblemDetails() { Detail = Detail, }; var responseBodyStream = new MemoryStream(); var httpContext = CreateHttpContext(responseBodyStream); var serializerOptions = new JsonOptions().SerializerOptions; _ = new NotFound<ProblemDetails>(value); // Act await HttpResultsHelper.WriteResultAsJsonAsync(httpContext, NullLogger.Instance, value, jsonSerializerOptions: serializerOptions); // Assert var body = JsonSerializer.Deserialize<ProblemDetails>(responseBodyStream.ToArray(), serializerOptions); Assert.NotNull(body); Assert.Equal(Detail, body.Detail); Assert.Equal(StatusCodes.Status404NotFound, body.Status); Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", body.Type); Assert.Equal("Not Found", body.Title); } private static async IAsyncEnumerable<JsonTodo> GetTodosAsync() { yield return new JsonTodo() { Id = 1, IsComplete = true, Name = "One" }; // ensure this is async await Task.Yield(); yield return new JsonTodo() { Id = 2, IsComplete = false, Name = "Two" }; yield return new TodoJsonChild() { Id = 3, IsComplete = true, Name = "Three", Child = "ThreeChild" }; } private static DefaultHttpContext CreateHttpContext(Stream stream) => new() { RequestServices = CreateServices(), Response = { Body = stream, }, }; private static IServiceProvider CreateServices() { var services = new ServiceCollection(); services.AddSingleton<ILoggerFactory, NullLoggerFactory>(); return services.BuildServiceProvider(); } [JsonSerializable(typeof(Todo))] [JsonSerializable(typeof(TodoChild))] [JsonSerializable(typeof(JsonTodo))] [JsonSerializable(typeof(TodoStruct))] [JsonSerializable(typeof(IAsyncEnumerable<JsonTodo>))] [JsonSerializable(typeof(JsonTodo[]))] private partial class TestJsonContext : JsonSerializerContext { } private class Todo { public int Id { get; set; } public string Name { get; set; } = "Todo"; public bool IsComplete { get; set; } } private struct TodoStruct { public TodoStruct() { } public int Id { get; set; } public string Name { get; set; } = "Todo"; public bool IsComplete { get; set; } } private class TodoChild : Todo { public string Child { get; set; } } [JsonDerivedType(typeof(TodoJsonChild), nameof(TodoJsonChild))] private class JsonTodo : Todo { } private class TodoJsonChild : JsonTodo { public string Child { get; set; } } }