Add converters for ProblemDetails and ValidationProblemDetails (#12216)

* Add converters for ProblemDetails and ValidationProblemDetails

ProblemDetails & ValidationProblemDetails require IgnoreNullValues to be
applied on the types. We'll use a converter to workaround the absence of this
feature

Fixes https://github.com/aspnet/AspNetCore/issues/11522
This commit is contained in:
Pranav K 2019-07-22 09:40:04 -07:00 committed by GitHub
parent f8c22859a0
commit a99ab25700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 545 additions and 35 deletions

View File

@ -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<string, object> 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<string, string[]> errors) { }
[System.Text.Json.Serialization.JsonPropertyNameAttribute("errors")]
public System.Collections.Generic.IDictionary<string, string[]> Errors { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
public partial class VirtualFileResult : Microsoft.AspNetCore.Mvc.FileResult

View File

@ -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<ProblemDetails>
{
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);
}
}
}
}

View File

@ -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<ValidationProblemDetails>
{
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<Dictionary<string, string[]>>(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();
}
}
}

View File

@ -4,12 +4,14 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc.Infrastructure;
namespace Microsoft.AspNetCore.Mvc
{
/// <summary>
/// A machine-readable format for specifying errors in HTTP API responses based on https://tools.ietf.org/html/rfc7807.
/// </summary>
[JsonConverter(typeof(ProblemDetailsJsonConverter))]
public class ProblemDetails
{
/// <summary>
@ -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".
/// </summary>
[JsonPropertyName("type")]
public string Type { get; set; }
/// <summary>
@ -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).
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.
/// </summary>
[JsonPropertyName("status")]
public int? Status { get; set; }
/// <summary>
/// A human-readable explanation specific to this occurrence of the problem.
/// </summary>
[JsonPropertyName("detail")]
public string Detail { get; set; }
/// <summary>
/// A URI reference that identifies the specific occurrence of the problem.It may or may not yield further information if dereferenced.
/// </summary>
[JsonPropertyName("instance")]
public string Instance { get; set; }
/// <summary>

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -507,4 +507,7 @@
<data name="ObjectResultExecutor_MaxEnumerationExceeded" xml:space="preserve">
<value>'{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&lt;&gt;' 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.</value>
</data>
</root>
<data name="UnexpectedJsonEnd" xml:space="preserve">
<value>Unexcepted end when reading JSON.</value>
</data>
</root>

View File

@ -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
/// <summary>
/// A <see cref="ProblemDetails"/> for validation errors.
/// </summary>
[JsonConverter(typeof(ValidationProblemDetailsJsonConverter))]
public class ValidationProblemDetails : ProblemDetails
{
/// <summary>
@ -83,6 +86,7 @@ namespace Microsoft.AspNetCore.Mvc
/// <summary>
/// Gets the validation errors associated with this instance of <see cref="ValidationProblemDetails"/>.
/// </summary>
[JsonPropertyName("errors")]
public IDictionary<string, string[]> Errors { get; } = new Dictionary<string, string[]>(StringComparer.Ordinal);
}
}

View File

@ -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<JsonException>(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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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]