当无效的JsonConverter时产生400 BadRequest吗?

时间:2019-12-17 08:10:31

标签: asp.net-core system.text.json

我正在将自定义JsonConverter与System.Text.Json配合使用,以使DateTime与所需的时区保持一致

/// <summary>
/// Converts a string to/from DateTime, requiring the timezone
/// </summary>
public class JsonDateTimeWithTimezoneConverter : JsonConverter<DateTime>
{
    //
    // FOR EXPLANATIONS
    //
    // see https://stackoverflow.com/a/58103218/1545567 and https://stackoverflow.com/a/17752389/1545567
    //



    private readonly string[] FORMATS = { 
        // Basic formats
        "yyyyMMddTHHmmsszzz",
        "yyyyMMddTHHmmsszz",
        "yyyyMMddTHHmmssZ",
        // Extended formats
        "yyyy-MM-ddTHH:mm:sszzz",
        "yyyy-MM-ddTHH:mm:sszz",
        "yyyy-MM-ddTHH:mm:ssZ",
        // All of the above with reduced accuracy to minutes
        "yyyyMMddTHHmmzzz",
        "yyyyMMddTHHmmzz",
        "yyyyMMddTHHmmZ",
        "yyyy-MM-ddTHH:mmzzz",
        "yyyy-MM-ddTHH:mmzz",
        "yyyy-MM-ddTHH:mmZ",            
    };

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        //TODO: 400 BadRequest instead of error 500 InternalServerError when format not respected
        Debug.Assert(typeToConvert == typeof(DateTime));
        return DateTime.ParseExact(reader.GetString(), FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:sszzz"));
    }
}

我在ConfigureServices

中这样注册
        services.AddControllers()
            .AddJsonOptions(options => {
                options.JsonSerializerOptions.Converters.Add(new JsonDateTimeWithTimezoneConverter());
            });

就像您在代码中看到的那样,当接收到的日期没有时区时,它将崩溃并产生异常,从而导致错误500 InternalServerError

如何在不触摸use app.UseExceptionHandler的情况下抛出异常以返回400(因为代码在我的库中)?

请注意,抛出的异常是FormatException,因此,对我来说,应将其转换为BadRequest ...

1 个答案:

答案 0 :(得分:1)

此问题应从ASP.NET Core 3.1开始修复:FormatException(由DateTime.ParseExact()方法抛出)现在在SystemTextJsonInputFormatter中被视为模型状态错误,即从3.0开始的默认输入格式化程序。这将导致返回400(而不是500)状态。请参见PR on Github,以及有关3.03.1的相关代码部分;

如果您仍在使用3.0,则可以捕获FormatException并重新抛出JsonException,这是在3.0中被视为模型状态错误的唯一异常类型:

try
{
    return DateTime.ParseExact(reader.GetString(), FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
}
catch(FormatException e)
{
    throw new JsonException();
}