diff --git a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs index 1368446b75..21f9d07064 100644 --- a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs +++ b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp3.0.cs @@ -960,12 +960,17 @@ namespace Microsoft.AspNetCore.Mvc public partial class ProblemDetails { public ProblemDetails() { } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("detail")] public string Detail { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } [System.Text.Json.Serialization.JsonExtensionDataAttribute] public System.Collections.Generic.IDictionary Extensions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("instance")] public string Instance { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("status")] public int? Status { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("title")] public string Title { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("type")] public string Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } } [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Method, AllowMultiple=false, Inherited=true)] @@ -1249,6 +1254,7 @@ namespace Microsoft.AspNetCore.Mvc public ValidationProblemDetails() { } public ValidationProblemDetails(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) { } public ValidationProblemDetails(System.Collections.Generic.IDictionary errors) { } + [System.Text.Json.Serialization.JsonPropertyNameAttribute("errors")] public System.Collections.Generic.IDictionary Errors { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } public partial class VirtualFileResult : Microsoft.AspNetCore.Mvc.FileResult diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ProblemDetailsJsonConverter.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ProblemDetailsJsonConverter.cs new file mode 100644 index 0000000000..8b7e1f5576 --- /dev/null +++ b/src/Mvc/Mvc.Core/src/Infrastructure/ProblemDetailsJsonConverter.cs @@ -0,0 +1,133 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Mvc.Core; + +namespace Microsoft.AspNetCore.Mvc.Infrastructure +{ + internal class ProblemDetailsJsonConverter : JsonConverter + { + private static readonly JsonEncodedText Type = JsonEncodedText.Encode("type"); + private static readonly JsonEncodedText Title = JsonEncodedText.Encode("title"); + private static readonly JsonEncodedText Status = JsonEncodedText.Encode("status"); + private static readonly JsonEncodedText Detail = JsonEncodedText.Encode("detail"); + private static readonly JsonEncodedText Instance = JsonEncodedText.Encode("instance"); + + public override ProblemDetails Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var problemDetails = new ProblemDetails(); + + if (!reader.Read()) + { + throw new JsonException(Resources.UnexpectedJsonEnd); + } + + while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) + { + ReadValue(ref reader, problemDetails, options); + } + + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException(Resources.UnexpectedJsonEnd); + } + + return problemDetails; + } + + public override void Write(Utf8JsonWriter writer, ProblemDetails value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + WriteProblemDetails(writer, value, options); + writer.WriteEndObject(); + } + + internal static void ReadValue(ref Utf8JsonReader reader, ProblemDetails value, JsonSerializerOptions options) + { + if (TryReadStringProperty(ref reader, Type, out var propertyValue)) + { + value.Type = propertyValue; + } + else if (TryReadStringProperty(ref reader, Title, out propertyValue)) + { + value.Title = propertyValue; + } + else if (TryReadStringProperty(ref reader, Detail, out propertyValue)) + { + value.Detail = propertyValue; + } + else if (TryReadStringProperty(ref reader, Instance, out propertyValue)) + { + value.Instance = propertyValue; + } + else if (reader.ValueTextEquals(Status.EncodedUtf8Bytes)) + { + reader.Read(); + if (reader.TokenType == JsonTokenType.Null) + { + // Nothing to do here. + } + else + { + value.Status = reader.GetInt32(); + } + } + else + { + var key = reader.GetString(); + reader.Read(); + value.Extensions[key] = JsonSerializer.Deserialize(ref reader, typeof(object), options); + } + } + + internal static bool TryReadStringProperty(ref Utf8JsonReader reader, JsonEncodedText propertyName, out string value) + { + if (!reader.ValueTextEquals(propertyName.EncodedUtf8Bytes)) + { + value = default; + return false; + } + + reader.Read(); + value = reader.GetString(); + return true; + } + + internal static void WriteProblemDetails(Utf8JsonWriter writer, ProblemDetails value, JsonSerializerOptions options) + { + if (value.Type != null) + { + writer.WriteString(Type, value.Type); + } + + if (value.Title != null) + { + writer.WriteString(Title, value.Title); + } + + if (value.Status != null) + { + writer.WriteNumber(Status, value.Status.Value); + } + + if (value.Detail != null) + { + writer.WriteString(Detail, value.Detail); + } + + if (value.Instance != null) + { + writer.WriteString(Instance, value.Instance); + } + + foreach (var kvp in value.Extensions) + { + writer.WritePropertyName(kvp.Key); + JsonSerializer.Serialize(writer, kvp.Value, kvp.Value?.GetType() ?? typeof(object), options); + } + } + } +} diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ValidationProblemDetailsJsonConverter.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ValidationProblemDetailsJsonConverter.cs new file mode 100644 index 0000000000..d112ff7f18 --- /dev/null +++ b/src/Mvc/Mvc.Core/src/Infrastructure/ValidationProblemDetailsJsonConverter.cs @@ -0,0 +1,66 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Mvc.Core; +using static Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsJsonConverter; + +namespace Microsoft.AspNetCore.Mvc.Infrastructure +{ + internal class ValidationProblemDetailsJsonConverter : JsonConverter + { + private static readonly JsonEncodedText Errors = JsonEncodedText.Encode("errors"); + + public override ValidationProblemDetails Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var problemDetails = new ValidationProblemDetails(); + + if (!reader.Read()) + { + throw new JsonException(Resources.UnexpectedJsonEnd); + } + + while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) + { + if (reader.ValueTextEquals(Errors.EncodedUtf8Bytes)) + { + var errors = JsonSerializer.Deserialize>(ref reader, options); + foreach (var item in errors) + { + problemDetails.Errors[item.Key] = item.Value; + } + } + else + { + ReadValue(ref reader, problemDetails, options); + } + } + + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException(Resources.UnexpectedJsonEnd); + } + + return problemDetails; + } + + public override void Write(Utf8JsonWriter writer, ValidationProblemDetails value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + WriteProblemDetails(writer, value, options); + + writer.WriteStartObject(Errors); + foreach (var kvp in value.Errors) + { + writer.WritePropertyName(kvp.Key); + JsonSerializer.Serialize(writer, kvp.Value, kvp.Value?.GetType() ?? typeof(object), options); + } + writer.WriteEndObject(); + + writer.WriteEndObject(); + } + } +} diff --git a/src/Mvc/Mvc.Core/src/ProblemDetails.cs b/src/Mvc/Mvc.Core/src/ProblemDetails.cs index e5e1ad31c3..709455e60a 100644 --- a/src/Mvc/Mvc.Core/src/ProblemDetails.cs +++ b/src/Mvc/Mvc.Core/src/ProblemDetails.cs @@ -4,12 +4,14 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Microsoft.AspNetCore.Mvc { /// /// A machine-readable format for specifying errors in HTTP API responses based on https://tools.ietf.org/html/rfc7807. /// + [JsonConverter(typeof(ProblemDetailsJsonConverter))] public class ProblemDetails { /// @@ -18,6 +20,7 @@ namespace Microsoft.AspNetCore.Mvc /// (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be /// "about:blank". /// + [JsonPropertyName("type")] public string Type { get; set; } /// @@ -25,21 +28,25 @@ namespace Microsoft.AspNetCore.Mvc /// of the problem, except for purposes of localization(e.g., using proactive content negotiation; /// see[RFC7231], Section 3.4). /// + [JsonPropertyName("title")] public string Title { get; set; } /// /// The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. /// + [JsonPropertyName("status")] public int? Status { get; set; } /// /// A human-readable explanation specific to this occurrence of the problem. /// + [JsonPropertyName("detail")] public string Detail { get; set; } /// /// A URI reference that identifies the specific occurrence of the problem.It may or may not yield further information if dereferenced. /// + [JsonPropertyName("instance")] public string Instance { get; set; } /// diff --git a/src/Mvc/Mvc.Core/src/Resources.resx b/src/Mvc/Mvc.Core/src/Resources.resx index 43d3e79b84..a255bcf725 100644 --- a/src/Mvc/Mvc.Core/src/Resources.resx +++ b/src/Mvc/Mvc.Core/src/Resources.resx @@ -1,17 +1,17 @@  - @@ -507,4 +507,7 @@ '{0}' reached the configured maximum size of the buffer when enumerating a value of type '{1}'. This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, consider ways to reduce the collection size, or consider manually converting '{1}' into a list rather than increasing the limit. - + + Unexcepted end when reading JSON. + + \ No newline at end of file diff --git a/src/Mvc/Mvc.Core/src/ValidationProblemDetails.cs b/src/Mvc/Mvc.Core/src/ValidationProblemDetails.cs index 64f922a16c..7df032255f 100644 --- a/src/Mvc/Mvc.Core/src/ValidationProblemDetails.cs +++ b/src/Mvc/Mvc.Core/src/ValidationProblemDetails.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using Microsoft.AspNetCore.Mvc.Core; +using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ModelBinding; namespace Microsoft.AspNetCore.Mvc @@ -11,6 +13,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// A for validation errors. /// + [JsonConverter(typeof(ValidationProblemDetailsJsonConverter))] public class ValidationProblemDetails : ProblemDetails { /// @@ -83,6 +86,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// Gets the validation errors associated with this instance of . /// + [JsonPropertyName("errors")] public IDictionary Errors { get; } = new Dictionary(StringComparer.Ordinal); } } diff --git a/src/Mvc/Mvc.Core/test/Infrastructure/ProblemDetailsConverterTest.cs b/src/Mvc/Mvc.Core/test/Infrastructure/ProblemDetailsConverterTest.cs new file mode 100644 index 0000000000..aad71ca605 --- /dev/null +++ b/src/Mvc/Mvc.Core/test/Infrastructure/ProblemDetailsConverterTest.cs @@ -0,0 +1,147 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Text; +using System.Text.Json; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.Infrastructure +{ + public class ProblemDetailsConverterTest + { + private static JsonSerializerOptions JsonSerializerOptions => new JsonOptions().JsonSerializerOptions; + + [Fact] + public void Read_ThrowsIfJsonIsIncomplete() + { + // Arrange + var json = "{"; + var converter = new ProblemDetailsJsonConverter(); + + // Act & Assert + var ex = Record.Exception(() => + { + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + converter.Read(ref reader, typeof(ProblemDetails), JsonSerializerOptions); + }); + Assert.IsAssignableFrom(ex); + } + + [Fact] + public void Read_Works() + { + // Arrange + var type = "https://tools.ietf.org/html/rfc7231#section-6.5.4"; + var title = "Not found"; + var status = 404; + var detail = "Product not found"; + var instance = "http://example.com/products/14"; + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var json = $"{{\"type\":\"{type}\",\"title\":\"{title}\",\"status\":{status},\"detail\":\"{detail}\", \"instance\":\"{instance}\",\"traceId\":\"{traceId}\"}}"; + var converter = new ProblemDetailsJsonConverter(); + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + + // Act + var problemDetails = converter.Read(ref reader, typeof(ProblemDetails), JsonSerializerOptions); + + Assert.Equal(type, problemDetails.Type); + Assert.Equal(title, problemDetails.Title); + Assert.Equal(status, problemDetails.Status); + Assert.Equal(instance, problemDetails.Instance); + Assert.Equal(detail, problemDetails.Detail); + Assert.Collection( + problemDetails.Extensions, + kvp => + { + Assert.Equal("traceId", kvp.Key); + Assert.Equal(traceId, kvp.Value.ToString()); + }); + } + + [Fact] + public void Read_WithSomeMissingValues_Works() + { + // Arrange + var type = "https://tools.ietf.org/html/rfc7231#section-6.5.4"; + var title = "Not found"; + var status = 404; + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var json = $"{{\"type\":\"{type}\",\"title\":\"{title}\",\"status\":{status},\"traceId\":\"{traceId}\"}}"; + var converter = new ProblemDetailsJsonConverter(); + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + + // Act + var problemDetails = converter.Read(ref reader, typeof(ProblemDetails), JsonSerializerOptions); + + Assert.Equal(type, problemDetails.Type); + Assert.Equal(title, problemDetails.Title); + Assert.Equal(status, problemDetails.Status); + Assert.Collection( + problemDetails.Extensions, + kvp => + { + Assert.Equal("traceId", kvp.Key); + Assert.Equal(traceId, kvp.Value.ToString()); + }); + } + + [Fact] + public void Write_Works() + { + // Arrange + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var value = new ProblemDetails + { + Title = "Not found", + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", + Status = 404, + Detail = "Product not found", + Instance = "http://example.com/products/14", + Extensions = + { + { "traceId", traceId }, + { "some-data", new[] { "value1", "value2" } } + } + }; + var expected = $"{{\"type\":\"{JsonEncodedText.Encode(value.Type)}\",\"title\":\"{value.Title}\",\"status\":{value.Status},\"detail\":\"{value.Detail}\",\"instance\":\"{JsonEncodedText.Encode(value.Instance)}\",\"traceId\":\"{traceId}\",\"some-data\":[\"value1\",\"value2\"]}}"; + var converter = new ProblemDetailsJsonConverter(); + var stream = new MemoryStream(); + + // Act + using (var writer = new Utf8JsonWriter(stream)) + { + converter.Write(writer, value, JsonSerializerOptions); + } + + // Assert + var actual = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal(expected, actual); + } + + [Fact] + public void Write_WithSomeMissingContent_Works() + { + // Arrange + var value = new ProblemDetails + { + Title = "Not found", + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", + Status = 404, + }; + var expected = $"{{\"type\":\"{JsonEncodedText.Encode(value.Type)}\",\"title\":\"{value.Title}\",\"status\":{value.Status}}}"; + var converter = new ProblemDetailsJsonConverter(); + var stream = new MemoryStream(); + + // Act + using (var writer = new Utf8JsonWriter(stream)) + { + converter.Write(writer, value, JsonSerializerOptions); + } + + // Assert + var actual = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal(expected, actual); + } + } +} diff --git a/src/Mvc/Mvc.Core/test/Infrastructure/ValidationProblemDetailsConverterTest.cs b/src/Mvc/Mvc.Core/test/Infrastructure/ValidationProblemDetailsConverterTest.cs new file mode 100644 index 0000000000..f55da67a20 --- /dev/null +++ b/src/Mvc/Mvc.Core/test/Infrastructure/ValidationProblemDetailsConverterTest.cs @@ -0,0 +1,145 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.Infrastructure +{ + public class ValidationProblemDetailsConverterTest + { + private static JsonSerializerOptions JsonSerializerOptions => new JsonOptions().JsonSerializerOptions; + + [Fact] + public void Read_Works() + { + // Arrange + var type = "https://tools.ietf.org/html/rfc7231#section-6.5.4"; + var title = "Not found"; + var status = 404; + var detail = "Product not found"; + var instance = "http://example.com/products/14"; + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var json = $"{{\"type\":\"{type}\",\"title\":\"{title}\",\"status\":{status},\"detail\":\"{detail}\", \"instance\":\"{instance}\",\"traceId\":\"{traceId}\"," + + "\"errors\":{\"key0\":[\"error0\"],\"key1\":[\"error1\",\"error2\"]}}"; + var converter = new ValidationProblemDetailsJsonConverter(); + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + + // Act + var problemDetails = converter.Read(ref reader, typeof(ValidationProblemDetails), JsonSerializerOptions); + + Assert.Equal(type, problemDetails.Type); + Assert.Equal(title, problemDetails.Title); + Assert.Equal(status, problemDetails.Status); + Assert.Equal(instance, problemDetails.Instance); + Assert.Equal(detail, problemDetails.Detail); + Assert.Collection( + problemDetails.Extensions, + kvp => + { + Assert.Equal("traceId", kvp.Key); + Assert.Equal(traceId, kvp.Value.ToString()); + }); + Assert.Collection( + problemDetails.Errors.OrderBy(kvp => kvp.Key), + kvp => + { + Assert.Equal("key0", kvp.Key); + Assert.Equal(new[] { "error0" }, kvp.Value); + }, + kvp => + { + Assert.Equal("key1", kvp.Key); + Assert.Equal(new[] { "error1", "error2" }, kvp.Value); + }); + } + + [Fact] + public void Read_WithSomeMissingValues_Works() + { + // Arrange + var type = "https://tools.ietf.org/html/rfc7231#section-6.5.4"; + var title = "Not found"; + var status = 404; + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var json = $"{{\"type\":\"{type}\",\"title\":\"{title}\",\"status\":{status},\"traceId\":\"{traceId}\"}}"; + var converter = new ProblemDetailsJsonConverter(); + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + + // Act + var problemDetails = converter.Read(ref reader, typeof(ProblemDetails), JsonSerializerOptions); + + Assert.Equal(type, problemDetails.Type); + Assert.Equal(title, problemDetails.Title); + Assert.Equal(status, problemDetails.Status); + Assert.Collection( + problemDetails.Extensions, + kvp => + { + Assert.Equal("traceId", kvp.Key); + Assert.Equal(traceId, kvp.Value.ToString()); + }); + } + + [Fact] + public void Write_Works() + { + // Arrange + var traceId = "|37dd3dd5-4a9619f953c40a16."; + var value = new ProblemDetails + { + Title = "Not found", + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", + Status = 404, + Detail = "Product not found", + Instance = "http://example.com/products/14", + Extensions = + { + { "traceId", traceId }, + { "some-data", new[] { "value1", "value2" } } + } + }; + var expected = $"{{\"type\":\"{JsonEncodedText.Encode(value.Type)}\",\"title\":\"{value.Title}\",\"status\":{value.Status},\"detail\":\"{value.Detail}\",\"instance\":\"{JsonEncodedText.Encode(value.Instance)}\",\"traceId\":\"{traceId}\",\"some-data\":[\"value1\",\"value2\"]}}"; + var converter = new ProblemDetailsJsonConverter(); + var stream = new MemoryStream(); + + // Act + using (var writer = new Utf8JsonWriter(stream)) + { + converter.Write(writer, value, JsonSerializerOptions); + } + + // Assert + var actual = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal(expected, actual); + } + + [Fact] + public void Write_WithSomeMissingContent_Works() + { + // Arrange + var value = new ProblemDetails + { + Title = "Not found", + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", + Status = 404, + }; + var expected = $"{{\"type\":\"{JsonEncodedText.Encode(value.Type)}\",\"title\":\"{value.Title}\",\"status\":{value.Status}}}"; + var converter = new ProblemDetailsJsonConverter(); + var stream = new MemoryStream(); + + // Act + using (var writer = new Utf8JsonWriter(stream)) + { + converter.Write(writer, value, JsonSerializerOptions); + } + + // Assert + var actual = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal(expected, actual); + } + } +} diff --git a/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs b/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs index 0de827952f..d7c6326ace 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs @@ -340,31 +340,31 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests { } - [Fact(Skip = "https://github.com/aspnet/AspNetCore/pull/11460")] + [Fact] public override Task ActionsReturnBadRequest_WhenModelStateIsInvalid() { return base.ActionsReturnBadRequest_WhenModelStateIsInvalid(); } - [Fact(Skip = "https://github.com/dotnet/corefx/issues/38769")] + [Fact] public override Task ClientErrorResultFilterExecutesForStatusCodeResults() { return base.ClientErrorResultFilterExecutesForStatusCodeResults(); } - [Fact(Skip = "https://github.com/dotnet/corefx/issues/38769")] + [Fact] public override Task SerializingProblemDetails_IgnoresNullValuedProperties() { return base.SerializingProblemDetails_IgnoresNullValuedProperties(); } - [Fact(Skip = "https://github.com/dotnet/corefx/issues/38769")] + [Fact] public override Task SerializingProblemDetails_WithAllValuesSpecified() { return base.SerializingProblemDetails_WithAllValuesSpecified(); } - [Fact(Skip = "https://github.com/dotnet/corefx/issues/38769")] + [Fact] public override Task SerializingValidationProblemDetails_WithExtensionData() { return base.SerializingValidationProblemDetails_WithExtensionData(); diff --git a/src/Mvc/test/Mvc.FunctionalTests/SystemTextJsonOutputFormatterTest.cs b/src/Mvc/test/Mvc.FunctionalTests/SystemTextJsonOutputFormatterTest.cs index ca38091a82..d508bfe731 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/SystemTextJsonOutputFormatterTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/SystemTextJsonOutputFormatterTest.cs @@ -4,7 +4,6 @@ using System.Net; using System.Threading.Tasks; using FormatterWebSite.Controllers; -using Newtonsoft.Json.Linq; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests @@ -33,7 +32,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests [Fact] public override Task Formatting_DictionaryType() => base.Formatting_DictionaryType(); - [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/11522")] + [Fact] public override Task Formatting_ProblemDetails() => base.Formatting_ProblemDetails(); [Fact]