JsonConverter 无效时生成 400 BadRequest?
Producing a 400 BadRequest when invalid JsonConverter?
我正在使用带有 System.Text.Json 的自定义 JsonConverter 以使 DateTime 具有所需的时区
/// <summary>
/// Converts a string to/from DateTime, requiring the timezone
/// </summary>
public class JsonDateTimeWithTimezoneConverter : JsonConverter<DateTime>
{
//
// FOR EXPLANATIONS
//
// see and
//
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
如何在不使用 app.UseExceptionHandler 的情况下抛出异常以 return 400(因为代码在我的库中)?
请注意,抛出的异常是 FormatException,所以对我来说,它应该被翻译成 BadRequest ...
此问题应从 ASP.NET Core 3.1 开始修复:FormatException
(由 DateTime.ParseExact()
方法抛出)现在在 [=13= 中被视为模型状态错误],这是自 3.0 以来的默认输入格式化程序。这将导致返回 400 而不是 500 状态。见 PR on Github, and the relevant code sections for 3.0 and 3.1;
如果您仍在使用 3.0,您可以捕获 FormatException
并重新抛出 JsonException
,这是 3.0 中唯一被视为模型状态错误的异常类型:
try
{
return DateTime.ParseExact(reader.GetString(), FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
}
catch(FormatException e)
{
throw new JsonException();
}
我正在使用带有 System.Text.Json 的自定义 JsonConverter 以使 DateTime 具有所需的时区
/// <summary>
/// Converts a string to/from DateTime, requiring the timezone
/// </summary>
public class JsonDateTimeWithTimezoneConverter : JsonConverter<DateTime>
{
//
// FOR EXPLANATIONS
//
// see and
//
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
如何在不使用 app.UseExceptionHandler 的情况下抛出异常以 return 400(因为代码在我的库中)?
请注意,抛出的异常是 FormatException,所以对我来说,它应该被翻译成 BadRequest ...
此问题应从 ASP.NET Core 3.1 开始修复:FormatException
(由 DateTime.ParseExact()
方法抛出)现在在 [=13= 中被视为模型状态错误],这是自 3.0 以来的默认输入格式化程序。这将导致返回 400 而不是 500 状态。见 PR on Github, and the relevant code sections for 3.0 and 3.1;
如果您仍在使用 3.0,您可以捕获 FormatException
并重新抛出 JsonException
,这是 3.0 中唯一被视为模型状态错误的异常类型:
try
{
return DateTime.ParseExact(reader.GetString(), FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
}
catch(FormatException e)
{
throw new JsonException();
}